SpringBoot+Shiro

SpringBoot+Shiro

总体来看,对Shiro的操作,是围绕Realm的对象来进行操作的,Realm提供的是待校验数据的比对值,即安全数据源

Subject currentuser = SecurityUtils.getSubject();
Session session = currentuser.getSession();
currentUser.isAuthenticated()
currentUser. getPrincipal()
currentUser.hasRo1e ("schwartz")
currentUser.isPermitted("7ightsaber:wie1d")currentUser. logout();
<!-- shiro -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.9.0</version>
</dependency>

shiro是如何工作的?

从外部来看,从应用程序的角度来观察

  1. Application
  2. Subject (the current User)
  3. Shiro SecurityManagrer (manager all user)
  4. Realm (access your security data)
  • 创建一个Shiro的 Configuration 类 需要使用 @Configuration 注解
    1. 先创建 realm 对象,UserRealm
    2. 创建 DefaultWebSecurityManager 对象
    3. 创建 ShiroFilterFactoryBean 对象
      都需要使用@Bean注册bean
  • 自定义一个UserRealm类 继承AuthorizingRealm
    业务一般写这里
    一般创建顺序:
    • 重写里面的两个方法 授权和认证
    • AuthorizationInfo
    • AuthenticationInfo
  • 登录拦截:
  • SimpleAuthenticationInfo
    MD5加密,MD5盐值加密:会在后面加上你的username

UserRealm相关知识点:https://blog.csdn.net/weixin_38297879/article/details/81317625

具体代码:

  • Controller

        /**
         * @return 登录页面
         */
        @RequestMapping("/login")
        public String toLogin(String userName,String passWord, Model model, HttpSession session){
            //获取当前的用户
            Subject currentUser = SecurityUtils.getSubject();
            //封装用户的登陆数据  放入令牌加密
            UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord);
            try {
                currentUser.login( token );
                session.setAttribute("isLogin",userMapper.login(userName,passWord).getUserName());
            } catch ( UnknownAccountException uae ) {
                model.addAttribute("errorMsg","用户名不存在!");
                return "login";
            } catch ( IncorrectCredentialsException ice ) {
                model.addAttribute("errorMsg","密码错误!");
                return "login";
            } catch ( LockedAccountException lae ) {
                model.addAttribute("errorMsg","账号被冻结!");
                return "login";
            } catch ( AuthenticationException ae ) {
                model.addAttribute("errorMsg","条件错误!");
            }
            return "index";
        }
    
  • UserRealm

    public class UserRealm extends AuthorizingRealm {
    
        @Autowired
        private UserMapper userMapper;
    
        //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            System.out.println("执行了=>授权doGetAuthorizationInfo");
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    //        info.addStringPermission("user:add");
            Subject subject = SecurityUtils.getSubject();
            // 拿到当前的User对象
            UserInfo currentUser = (UserInfo) subject.getPrincipal();
            info.addStringPermission(currentUser.getPerms());
            return info;
        }
    
        //认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("执行了=>认证doGetAuthenticationInfo");
            UsernamePasswordToken userToken = (UsernamePasswordToken) token;
            UserInfo user = userMapper.queryUserByName(userToken.getUsername());
            if (user==null){
                // UnknowAccountException
                return null;
            }
            //SimpleAuthenticationInfo(principal:当前认证的用户,credentials:传递的密码对象,realmName:用户名)
            return new SimpleAuthenticationInfo(user,user.getPassWord(),"");
        }
    }
    
    
  • ShiroConfig

    @Configuration
    public class ShiroConfig {
    
        //3. 创建 ShiroFilterFactoryBean 对象
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
            ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
            // 设置安全管理器
            bean.setSecurityManager(defaultWebSecurityManager);
            //添加shiro的内置过滤器
            /*
                anon: 无需认证就可以访问
                authc: 必须认证才可以访问
                user: 必须拥有记住我 功能才能被使用(所以一般不用)
                perms: 拥有对某个资源的权限才能访问
                role: 拥有某个角色才能访问
             */
            Map<String, String> filterMap = new LinkedHashMap<>();
            //  支持通配符
            filterMap.put("/add","perms[user:add]");
            filterMap.put("/*/*","authc");
    //        filterMap.put("/add","authc");
            bean.setLoginUrl("/login");
            bean.setUnauthorizedUrl("/unauth");
            bean.setFilterChainDefinitionMap(filterMap);
            return bean;
        }
        //2. 创建 DefaultWebSecurityManager 对象
        @Bean(name = "securityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRealm(userRealm);
            return securityManager;
        }
        //1. 先创建 realm 对象,UserRealm
        @Bean(name = "userRealm")
        public UserRealm userRealm(){
            return new UserRealm();
        }
        
        //整合ShiroDialect:用来整合shiro和thymeleaf
        @Bean
        public ShiroDialect getShiroDialect(){
            return new ShiroDialect();
        }
    }
    
    

在shiro配置文件中注入一个bean

//整合ShiroDialect:用来整合shiro和thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
<!-- shiro-thymeleaf整合-->
<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.1.0</version>
</dependency>

在thymeleaf的html中引入命名空间:
xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a th:href="@{user/ds}">管理界面</a>
    <a th:href="@{user/list}">员工列表</a>
    <a shiro:guest="true" th:href="@{login}">登录</a>
    <div shiro:hasPermission="user:add"><a th:href="@{add}">add</a></div>
    <div shiro:hasPermission="user:update"><a th:href="@{update}">update</a></div>
</body>
</html>
  • shiro:guest="true"
    判断当前是否存在认证过的用户,有则不显示该内容,没有则显示
  • shiro:hasPermission="user:update"
    判断当前用户是拥有对应权限,有则显示,没有则不显示
posted @ 2022-05-10 09:35  没有烦恼的猫猫  阅读(135)  评论(0编辑  收藏  举报