Shiro三大核心:
1、Subject:代表当前用户
2、SecurityManager:shiro核心管理器
3、realm:类似data层,用于认证授权

三大核心

内部构造

一、pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>site.kexing</groupId>
    <artifactId>shiro-springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>shiro-springboot</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <!-- thymeleaf-extras-shiro -->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
        <!-- shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

二、ShiroConfig(重点)

@Configuration
public class ShiroConfig {
    //3、ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Autowired DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);

        //添加shiro的内置过滤器
        /**
         * anon:无需认证即可访问
         * authc:必须认证才能访问
         * user:必须拥有记住我功能才能用
         * perms:拥有对某个资源的权限才能访问
         * role:拥有某个角色权限才能访问
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
        //必须认证才能访问
//        filterMap.put("/user/adduser","authc");
//        filterMap.put("/user/updateuser","authc");
        filterMap.put("/user/adduser","perms[user:add]");
        filterMap.put("/user/updateuser","perms[user:update]");
        filterMap.put("/user/**","perms[user]");
        bean.setFilterChainDefinitionMap(filterMap);

        //设置未登录时跳到登录页面
        bean.setLoginUrl("/tologin");
        //未经授权无法访问
        bean.setUnauthorizedUrl("/unauth");

        return bean;
    }

    //2、DefaultWebSecurityManager
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Autowired UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联userRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //1、创建UserRealm 需自定义类
    @Bean
    public UserRealm getUserRealm(){
        return new UserRealm();
    }

    //shiro整合thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}

三、自定义realm继承AuthorizingRealm(重点)

public class UserRealm extends AuthorizingRealm {
    @Autowired
    UserMapper userMapper;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("AuthorizationInfo->执行了授权");
        //SimpleAuthorizationInfo
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前登录的对象
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal();
        //授权
        info.addStringPermission(currentUser.getPerms());
        System.out.println("当前用户授权完毕");
        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("AuthenticationInfo->执行了认证");
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        System.out.println("realm:"+token);
        User user = userMapper.selectUserByName(token.getUsername());
        if(user == null){
            return null;
        }
        System.out.println("认证中");
        //密码认证
        return new SimpleAuthenticationInfo(user,user.getPwd(),"");
    }
}

四、登录controller

@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login(String username, String password, Model model){
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        System.out.println("controller:"+token);
        try {
            //执行登录方法
            System.out.println("登录方法执行前");
            subject.login(token);
            System.out.println("执行了登录");
            return "index";
        }catch (UnknownAccountException u){
            //用户不存在
            model.addAttribute("msg","用户名不存在");
            return "login";
        }catch (IncorrectCredentialsException i){
            //用户不存在
            model.addAttribute("msg","密码不正确");
            return "login";
        }

    }
}

五、跳转路由

@Controller
public class RouterController {
    @RequestMapping({"/","toindex"})
    public String toIndex(Model model){
        model.addAttribute("msg","hello shiro");
        return "index";
    }

    @RequestMapping("/user/adduser")
    public String toAddUser(){
        return "/user/addUser";
    }

    @RequestMapping("/user/updateuser")
    public String toUpdateUser(){
        return "/user/updateUser";
    }

    @RequestMapping("/tologin")
    public String toLogin(){
        return "login";
    }

    @ResponseBody
    @RequestMapping("/unauth")
    public String unauth(){
        return "未经授权无法访问";
    }
    
}

六、实体、mapper

User:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String uname;
    private String pwd;
    private String perms;
}

mapper:

<select id="selectUserByName" parameterType="string" resultType="user">
        select * from user where uname = #{uname}
    </select>
最后修改:2021 年 11 月 15 日 05 : 17 PM
如果觉得我的文章对你有用,请随意赞赏