• shiro的简单介绍


    1.Shiro的简单配置

    1) 获取ShiroFilterFactoryBean,作用是在执行相关操作前,先进行功能过滤,拦截所有请求,进入到shiro中进行认证与授权
    例如:设置一些拦截的请求
    // 身份认证失败,则跳转到登录页面的配置
    bean.setLoginUrl(“/tologin”);
    // 权限认证失败,则跳转到指定页面
    bean.setUnauthorizedUrl(“/tologin”);

    2) 创建SecurityManager,来管理shiro;Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。

    3) Realm 充当了 Shiro 与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro 会从应用配置的 Realm 中查找用户及其权限信息,可见Realm的重要。
    当配置 Shiro时,你必须至少指定一个 Realm ,用于认证和(或)授权。配置多个 Realm 是可以的,但是至少需要一个。

    Shiro默认使用自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm,以userRealm为例子。

    shiroConfig配置:

    package com.example.demo.config;
    
    import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    @Configuration
    public class ShiroConfig {
    
        //ShiroFilterFactoryBean
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
            ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
            //设置安全管理器
            bean.setSecurityManager(defaultWebSecurityManager);
    
           /* // 身份认证失败,则跳转到登录页面的配置
            bean.setLoginUrl("/tologin");
            // 权限认证失败,则跳转到指定页面
            bean.setUnauthorizedUrl("/tologin");*/
    
            //添加shiro的内置过滤器
    
            /**
             * anno 无需认证就可以访问必须认证了才能访问
             *authc
             * user:必须拥有记住我功能才适用
             * perms :拥有对某个资源的权限才能访问
             * role:拥有某个角色的权限
             */
    
            //拦截请求
    //        Map filterChainDefinitionMap =new LinkedHashMap<>();
    
    //        filterChainDefinitionMap.put("/tologin","authc");//免登录验证
    
    //        filterChainDefinitionMap.put("/user/update","anon");//免登录验证
    //        filterChainDefinitionMap.put("/user/**","authc");//支持通配符操作  authc
    //        filterChainDefinitionMap.put("/user/add","authc");//身份验证
    
            //方式一:anon,authc
            Map filterChainDefinitionMap =new LinkedHashMap<>();
    
            filterChainDefinitionMap.put("/user/add","anon");
            filterChainDefinitionMap.put("/user/update","authc");
    //        filterChainDefinitionMap.put("/**","authc");//支持通配符操作  authc
            bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    
    
           /*
           //方式二:perms
           Map filterMap =new LinkedHashMap<>();
    
            filterMap.put("/user/add","perms[user:add]");
            filterMap.put("/user/update","perms[user:update]");
            bean.setFilterChainDefinitionMap(filterMap);*/
    
    
           //方式三:roles  加上roleFilter 类,并在UserRealm增加info.addRole("user");
           /*Map filterMap =new LinkedHashMap<>();
    
            filterMap.put("/user/add","roles[user]");
            filterMap.put("/user/update","roles[leader]");
            bean.setFilterChainDefinitionMap(filterMap);*/
    
    
    
            bean.setLoginUrl("/tologin");
            //设置未授权的请求
            bean.setUnauthorizedUrl("/noauth");
    
            return bean;
        }
    
        //方式二:user
    
        /*
        登录接口加上  token.setRememberMe(true);
    
        
           当有记住我信息,或已登录,则显示标签体内容
        
    
         */
    
        //DefaultWebSecurityManager2
        @Bean
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
            DefaultWebSecurityManager securityManager =new DefaultWebSecurityManager();
            //关联userRealm
            securityManager.setRealm(userRealm);
            return securityManager;
        }
    
        //创建realm对象,需要自定义类1
        @Bean
        public UserRealm userRealm(){
            return new UserRealm();
        }
    
        //整合shiroDialect:用来整合shiro thymeleaf
        @Bean
        public ShiroDialect getShiroDialect(){
            return new ShiroDialect();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112

    userRealm配置

    package com.example.demo.config;
    
    
    import com.example.demo.pojo.User;
    import com.example.demo.service.imp.UserServiceImpl;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    
    public class UserRealm extends AuthorizingRealm {
        @Autowired
        UserServiceImpl userService;
    
        //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            System.out.println("执行了=>授权");
            SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
    
    //        info.addRole("user");
    
            info.addStringPermission("user:update");
            info.addStringPermission("user:add");
    
    
            //拿到当前用户登陆对象
            Subject subject= SecurityUtils.getSubject();
            User currentUser= (User) subject.getPrincipal();//拿到User对象
    //        info.addStringPermission(currentUser.getPerms());//设置当前用户对象
    
            return info;
        }
    
        //认证(用户的权限)
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("执行了=>认证");
    
    
    //        String name="陈汝旭";
    //        String password="123456";
    
            //连接真实数据库
            UsernamePasswordToken userToken =(UsernamePasswordToken) authenticationToken;
    //        if (!userToken.getUsername().equals(name)){
    //            return null; //抛出异常 unkonwAccountexception登录失败
    //        }
    //        //密码认证
    //        return new SimpleAuthenticationInfo("",password,"");
    
            User user=userService.queryUserByName(userToken.getUsername());//获取用户名
    
            String name=user.getName();
            String password=user.getPwd();
            if(user==null){//说明查无此人
                return null;
            }
            return new SimpleAuthenticationInfo(user,password,name);
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    问题:“当对用户执行认证(登录)和授权(访问控制)验证时,Shiro 会从应用配置的 Realm 中查找用户及其权限信息。”,怎么实现?

    2.认证的代码流程

    1)执行登录的方法
    subject.login(token);//执行登陆的方法
    2)研究一下login()的方法,进入源码
    在这里插入图片描述

    3)再进入实现类
    (这个login方法大多都是赋值的操作,我们可以只抓住主要的语句分析)
    在这里插入图片描述
    4)进入这个方法Subject subject = this.securityManager.login(this, token);的实现类
    在这里插入图片描述
    5)
    在这里插入图片描述
    6)都是一些异常处理信息,主要研究info = this.doAuthenticate(token);
    在这里插入图片描述
    7)这里以单realm来研究 doSingleRealmAuthentication
    ()

    在这里插入图片描述
    8)再继续下钻到了这里,主要研究 realm.getAuthenticationInfo(token);可以发现getAuthenticationInfo原来是抽象接口Realm的其中一个方法
    在这里插入图片描述
    9)紧接着进入realm的其中一个实现类AuthenticatingRealm
    (个人觉得研究源码可以不全看懂,尽量抓住主要的语句即可,因为获取缓存中的信息无法帮助我们研究流程,可以先不理会)

    在这里插入图片描述

    10)doGetAuthenticationInfo一直下钻进来,可以看到我们继承的子类的方法AuthenticationInfo,然后在自定义的AuthenticationInfo进行用户认证的操作。
    在这里插入图片描述
    在这里插入图片描述

    3.授权的代码流程

    shiro判断权限的方法有subject.isPermitted(“user”),subject.hasRole(“user”);等
    以subject.isPermitted(“user”)作为研究

    1)点进去它的实现类DelegatingSubject,先判断身份this.hasPrincipals(),在判断授权,所以主要研究isPermitted()
    在这里插入图片描述
    2)再继续点进去实现类AuthorizingRealm

    在这里插入图片描述
    3)主要研究getAuthorizationInfo()这个方法

    在这里插入图片描述
    4)根据上面说的经验,缓存的方法可以先不理会,这里大多也是一些异常处理信息,所以主要研究 info = this.doGetAuthorizationInfo(principals);

    在这里插入图片描述
    5)再点击进去,又到了我们的老朋友userRealm的doGetAuthorizationInfo
    在这里插入图片描述

    正常情况这里将从数据库中获取到相对应的权限信息
    (为了偷懒,这里就采用写死的方式获取权限)

    在这里插入图片描述

    4.三种权限认证的方式

    在这里插入图片描述

  • 相关阅读:
    Java Stream流指南:优雅处理集合数据
    【Express】登录鉴权 JWT
    Vuforia AR篇(三)— AR模型出场效果
    Multisim软件常用仪表的使用与一些基本测量方法
    AOP切面实现增删改防止重放攻击
    如何连接智汀智能窗帘电机?打工人回到家后的“躺平”模式
    轻松合并Excel工作表:Java批量操作优化技巧
    常见前端开发面试题
    【数据结构】反射、枚举
    文件包含漏洞-知识点
  • 原文地址:https://blog.csdn.net/m0_59092234/article/details/126496468