springboot整合Shiro

作者: 彬荣 | 来源:发表于2020-06-10 13:30 被阅读0次

    shiro权限控制架构

    shiro实现的认证

    1、从类的继承关系可以看出自定义的Realm只需要实现AuthorizingRealm类即可。

    Realm继承关系.png

    2、只需要实现下列两个方法即可
    doGetAuthorizationInfo 授权
    doGetAuthenticationInfo 认证

    shiro中的加密

    1. md5加密一般用来加密和做校验和

      • MD5算法不可逆,内容相同无论执行多少次MD5加密生成的结果始终一致。
        例如:可以对文件进行文件加密,保证文件的内容不被篡改
      • 网上常见的MD5解密,只是做了把简单的字符串进行穷举解密
      • MD5加密完始终是一个16进制的32位长度字符串

    Shiro中如何使用MD5加密认证

    1. 用户登录时的处理在Realm中添加秘钥认证器
    //给安全管理器设置realm
         CustomerMd5Realm customerMd5Realm=new CustomerMd5Realm();
         //自定义MD5秘钥匹配器
         HashedCredentialsMatcher hashedCredentialsMatcher=new HashedCredentialsMatcher();
         hashedCredentialsMatcher.setHashAlgorithmName("md5");//设置使用什么方式进行加密
         hashedCredentialsMatcher.setHashIterations(1024);//设置散列的次数
         customerMd5Realm.setCredentialsMatcher(hashedCredentialsMatcher);
    
    1. 在Realm中进行进行处理
      //ByteSource.Util.bytes("12121")是做加盐处理
       @Override
         protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
             String principal=(String)authenticationToken.getPrincipal();
             if("user".equals(principal)){
                 return new SimpleAuthenticationInfo(principal,"3aa17c6555fb36a1e20783b8cdacbd8e", ByteSource.Util.bytes("12121"),this.getName());
             }
             return null;
         }
      
      

    Shiro中实现授权

    1. 授权的概念

      • 授权,即访问控制,控制谁能访问哪些资源,主体进行身份认证后需要分配权限方可访问系统的资源,对于某些资源没有权限是没有权限访问的
      • 授权可以简单的理解为Who对What进行How操作
        • who:即主体Subject 主体需要访问系统中的资源。
        • what:即资源Resource,如系统菜单、页面、按钮、类方法等信息。资源包括资源类型和资源实例。
        • how:授权/许可,规定了主体对资源的操作许可,权限离开资源没有意义,如用户查询权限、用户添加权限、某个类方法的调用权限等,通过权限
          可知主体对哪些资源有哪些操作许可
    2. 授权的方式

      • 基于角色的访问控制

        • RBAC基于角色的访问控制(Role-Base Access Controll)是以角色为中心进行访问控制。

          if(subject.hasRole("admin")){
              //操作什么资源
          }
          
     - 基于资源的访问控制(Resource-Based Access Control)是以资源为中心进行访问控制。
    
       ```java
       if(subject.isPermission("user:*:create")){
           
       }
       ```
    
    1. 权限字符串
      • 权限字符串的规则:资源标识符:操作:资源实例标识符,意思是对哪个资源的哪个实例具有什么操作,权限字符串也可以使用*通配符。
        • 用户修改权限:user:create,或者user:create:*
        • 用户修改实例001的权限:user:update:001
        • 用户实例001的所有权限:user:*:001

    shiro中授权编程的方式

    • 编程方式

      if(subject.hasRole("admin")){
          
      }
      
    • 注解方式

      @RequiresRoles("admin")
      public void hello(){}
      
    • 标签方式

      jsp/GSP 标签在jsp页面通过相应的标签方式完成
      <shiro:hasRole name="admin">
      
      </shiro:hasRole>
      

    开发授权

    1. realm中实现

    shiro与springboot进行整合

    实现的方式

    springboot整合shiro需要通过Filter的方式对Url进行拦截处理

    实现过程

    pom文件引入包

     <!--添加shiro依赖-->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring-boot-starter</artifactId>
                <version>1.5.3</version>
            </dependency>
            <!--添加数据库访问-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.19</version>
            </dependency>
    

    定义配置类ShiroConfig

    在配置类中主要配置shiro的拦截器、shiro安全管理器、shiro访问数据库域、MD5加密

    • 配置拦截器
     /**
         * 定义拦截器
         * @param defaultWebSecurityManager
         * @return
         */
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
            //给filter设置公共安全管理器
            shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
            //配置访问权限
            HashMap<String, String > map = new HashMap<>();
            map.put("/user/login","anon");
            map.put("/user/register","anon");
            map.put("/user/logout","anon");
            map.put("/register.jsp","anon");
            map.put("/**","authc");
            shiroFilterFactoryBean.setLoginUrl("/login.jsp");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
            return shiroFilterFactoryBean;
        }
    
    • 注入安全管理器
    //创建安全管理器
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(AuthorizingRealm realm){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        realm.setCredentialsMatcher(getCredentialsMatcher());
        defaultWebSecurityManager.setRealm(realm);
        return  defaultWebSecurityManager;
    }
    
    • 创建自己的访问数据库域
    public class CustomRealm extends AuthorizingRealm {
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            String username=(String)principalCollection.getPrimaryPrincipal();
            if("liuxiaobin".equals(username)){
                SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
                simpleAuthorizationInfo.addRole("product");
                simpleAuthorizationInfo.addRole("log");
                return simpleAuthorizationInfo;
            }
            return null;
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            String username=(String)authenticationToken.getPrincipal();
            UserServiceImpl userService=(UserServiceImpl) SpringUtils.getBean("userService");
            User user=userService.getUserByUsername(username);
            SimpleAuthenticationInfo simpleAuthenticationInfo=null;
            if(user!=null) {
                simpleAuthenticationInfo= new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), ByteSource.Util.bytes(user.getSalt()),this.getName());
            }
            return simpleAuthenticationInfo;
        }
    }
    
    • 注入MD5加密加盐和散列处理
      @Bean
      public CredentialsMatcher getCredentialsMatcher(){
          //自定义MD5秘钥匹配器
          HashedCredentialsMatcher hashedCredentialsMatcher=new HashedCredentialsMatcher();
          hashedCredentialsMatcher.setHashAlgorithmName("md5");//设置使用什么方式进行加密
          hashedCredentialsMatcher.setHashIterations(1024);//设置散列的次数
          return  hashedCredentialsMatcher;
      }
    
    • 其他额外配置

      • 盐生成类

         public static String getSalt(int n){
                char[] charts="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!@@##!^%%$%$%$%$%$%$%$%$%@#(**&&&".toCharArray();
                StringBuilder sb=new StringBuilder();
                for (int i = 0; i < n; i++) {
                    char aChar=charts[new Random().nextInt(charts.length)];
                    sb.append(aChar);
                }
                return sb.toString();
            }
        
      • 获取Bean的工具类

        @Component
        public class SpringUtils implements ApplicationContextAware {
        
            private static ApplicationContext context;
        
            @Override
            public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext) throws BeansException {
                this.context=applicationContext;
            }
        
            public static Object getBean(String beanName){
                
                return context.getBean(beanName);
            }
        }
        
         
    
    ## shiro 缓存
    
    #### shiro整合ehcache
    
    - 添加ehche依赖
    
    ```xml
    <!--添加ehcache缓存配置-->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-ehcache</artifactId>
        <version>1.5.3</version>
    </dependency>
    
    • 配置realm中开启缓存

      @Bean
      public AuthorizingRealm getAuthorizingRealm(){
          CustomRealm customRealm = new CustomRealm();
          customRealm.setCredentialsMatcher(redentialsMatcher());//设置认证秘钥md5+salt+散列
          //开启缓存
          customRealm.setCachingEnabled(true);//开启全局缓存
          customRealm.setCacheManager(ehCacheManager());
          customRealm.setAuthenticationCachingEnabled(true);//开启认证缓存
          customRealm.setAuthenticationCacheName("AuthenticationCache");//设置认证缓存的名字
          customRealm.setAuthorizationCachingEnabled(true);//开启授权缓存
          customRealm.setAuthorizationCacheName("AuthorizationCache");//设置授权缓存的名字
          customRealm.setCacheManager(new EhCacheManager());//设置缓存管理器
      
          return customRealm;
      }
      

    shiro整合redis

    • 添加redis依赖

        <!--添加redis缓存配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
      
    • redis实现shiro中的CacheManager

      package com.bidr.springbootshiro.shiro.cache;
      import org.apache.shiro.cache.Cache;
      import org.apache.shiro.cache.CacheException;
      import org.apache.shiro.cache.CacheManager;
      import org.springframework.data.redis.core.RedisTemplate;
      public class RedisCacheShiroManager implements CacheManager {
          private RedisTemplate redisTemplate;
          public RedisCacheShiroManager(RedisTemplate redisTemplate){
              this.redisTemplate=redisTemplate;
          }
          @Override
          public <K, V> Cache<K, V> getCache(String s) throws CacheException {
              return new ReidsCacheShiro<K,V>(s,redisTemplate);
          }
      }
      
    • 设置redis的缓存

      package com.bidr.springbootshiro.shiro.cache;
      import org.apache.shiro.cache.Cache;
      import org.apache.shiro.cache.CacheException;
      import org.springframework.data.redis.core.RedisTemplate;
      import java.util.Collection;
      import java.util.Set;
      public class ReidsCacheShiro<K,V> implements Cache<K,V> {
      
          private RedisTemplate redisTemplate;
          private String name;
          public ReidsCacheShiro(String name,RedisTemplate redisTemplate) {
              this.redisTemplate = redisTemplate;
              this.name=name;
          }
      
      
          @Override
          public V get(K k) throws CacheException {
              System.out.println((V)redisTemplate.opsForValue().get(k.toString()));
              return (V)redisTemplate.opsForValue().get(k.toString());
          }
      
          @Override
          public V put(K k, V v) throws CacheException {
              redisTemplate.opsForValue().set(k.toString(),v);
              return v;
          }
      
          @Override
          public V remove(K k) throws CacheException {
              return null;
          }
      
          @Override
          public void clear() throws CacheException {
      
          }
      
          @Override
          public int size() {
              return 0;
          }
      
          @Override
          public Set<K> keys() {
              return null;
          }
      
          @Override
          public Collection<V> values() {
              return null;
          }
      }
      
      
    • shiroConfig中设置redisCacheManager

        @Bean
        public CacheManager redisCacheManager(){
            return new RedisCacheShiroManager(redisTemplate);
        }
        /**
        * 自定义realm实现
        * 1、设置MD5加密验证机制
        * 2、开启realm缓存
        * @return
        */
        @Bean
        public AuthorizingRealm getAuthorizingRealm(){
            CustomRealm customRealm = new CustomRealm();
            customRealm.setCredentialsMatcher(redentialsMatcher());//设置认证秘钥md5+salt+散列
            //开启缓存
            customRealm.setCachingEnabled(true);//开启全局缓存
            //customRealm.setCacheManager(ehCacheManager());
            customRealm.setCacheManager(redisCacheManager());
            customRealm.setAuthenticationCachingEnabled(true);//开启认证缓存
            customRealm.setAuthenticationCacheName("AuthenticationCache");//设置认证缓存的名字
            customRealm.setAuthorizationCachingEnabled(true);//开启授权缓存
            customRealm.setAuthorizationCacheName("AuthorizationCache");//设置授权缓存的名字
            customRealm.setCacheManager(new EhCacheManager());//设置缓存管理器
              return customRealm;
        }
      

    shiro 集成验证码

    相关文章

      网友评论

        本文标题:springboot整合Shiro

        本文链接:https://www.haomeiwen.com/subject/rhautktx.html