springboot整合Shiro

shiro權(quán)限控制架構(gòu)

shiro實(shí)現(xiàn)的認(rèn)證

1表锻、從類的繼承關(guān)系可以看出自定義的Realm只需要實(shí)現(xiàn)AuthorizingRealm類即可胀滚。

Realm繼承關(guān)系.png

2炼绘、只需要實(shí)現(xiàn)下列兩個(gè)方法即可
doGetAuthorizationInfo 授權(quán)
doGetAuthenticationInfo 認(rèn)證

shiro中的加密

  1. md5加密一般用來加密和做校驗(yàn)和

    • MD5算法不可逆替蛉,內(nèi)容相同無論執(zhí)行多少次MD5加密生成的結(jié)果始終一致吃警。
      例如:可以對文件進(jìn)行文件加密,保證文件的內(nèi)容不被篡改
    • 網(wǎng)上常見的MD5解密阀蒂,只是做了把簡單的字符串進(jìn)行窮舉解密
    • MD5加密完始終是一個(gè)16進(jìn)制的32位長度字符串

Shiro中如何使用MD5加密認(rèn)證

  1. 用戶登錄時(shí)的處理在Realm中添加秘鑰認(rèn)證器
//給安全管理器設(shè)置realm
     CustomerMd5Realm customerMd5Realm=new CustomerMd5Realm();
     //自定義MD5秘鑰匹配器
     HashedCredentialsMatcher hashedCredentialsMatcher=new HashedCredentialsMatcher();
     hashedCredentialsMatcher.setHashAlgorithmName("md5");//設(shè)置使用什么方式進(jìn)行加密
     hashedCredentialsMatcher.setHashIterations(1024);//設(shè)置散列的次數(shù)
     customerMd5Realm.setCredentialsMatcher(hashedCredentialsMatcher);
  1. 在Realm中進(jìn)行進(jìn)行處理
    //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中實(shí)現(xiàn)授權(quán)

  1. 授權(quán)的概念

    • 授權(quán)该窗,即訪問控制,控制誰能訪問哪些資源蚤霞,主體進(jìn)行身份認(rèn)證后需要分配權(quán)限方可訪問系統(tǒng)的資源酗失,對于某些資源沒有權(quán)限是沒有權(quán)限訪問的
    • 授權(quán)可以簡單的理解為Who對What進(jìn)行How操作
      • who:即主體Subject 主體需要訪問系統(tǒng)中的資源。
      • what:即資源Resource昧绣,如系統(tǒng)菜單规肴、頁面、按鈕夜畴、類方法等信息拖刃。資源包括資源類型和資源實(shí)例。
      • how:授權(quán)/許可贪绘,規(guī)定了主體對資源的操作許可兑牡,權(quán)限離開資源沒有意義,如用戶查詢權(quán)限税灌、用戶添加權(quán)限均函、某個(gè)類方法的調(diào)用權(quán)限等,通過權(quán)限
        可知主體對哪些資源有哪些操作許可
  2. 授權(quán)的方式

    • 基于角色的訪問控制

      • RBAC基于角色的訪問控制(Role-Base Access Controll)是以角色為中心進(jìn)行訪問控制垄琐。

        if(subject.hasRole("admin")){
            //操作什么資源
        }
        
 - 基于資源的訪問控制(Resource-Based Access Control)是以資源為中心進(jìn)行訪問控制边酒。

   ```java
   if(subject.isPermission("user:*:create")){
       
   }
   ```
  1. 權(quán)限字符串
    • 權(quán)限字符串的規(guī)則:資源標(biāo)識符:操作:資源實(shí)例標(biāo)識符经柴,意思是對哪個(gè)資源的哪個(gè)實(shí)例具有什么操作,權(quán)限字符串也可以使用*通配符狸窘。
      • 用戶修改權(quán)限:user:create,或者user:create:*
      • 用戶修改實(shí)例001的權(quán)限:user:update:001
      • 用戶實(shí)例001的所有權(quán)限:user:*:001

shiro中授權(quán)編程的方式

  • 編程方式

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

    @RequiresRoles("admin")
    public void hello(){}
    
  • 標(biāo)簽方式

    jsp/GSP 標(biāo)簽在jsp頁面通過相應(yīng)的標(biāo)簽方式完成
    <shiro:hasRole name="admin">
    
    </shiro:hasRole>
    

開發(fā)授權(quán)

  1. realm中實(shí)現(xiàn)

shiro與springboot進(jìn)行整合

實(shí)現(xiàn)的方式

springboot整合shiro需要通過Filter的方式對Url進(jìn)行攔截處理

實(shí)現(xiàn)過程

pom文件引入包

 <!--添加shiro依賴-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-starter</artifactId>
            <version>1.5.3</version>
        </dependency>
        <!--添加數(shù)據(jù)庫訪問-->
        <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訪問數(shù)據(jù)庫域翻擒、MD5加密

  • 配置攔截器
 /**
     * 定義攔截器
     * @param defaultWebSecurityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        //給filter設(shè)置公共安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        //配置訪問權(quán)限
        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;
    }
  • 注入安全管理器
//創(chuàng)建安全管理器
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(AuthorizingRealm realm){
    DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
    realm.setCredentialsMatcher(getCredentialsMatcher());
    defaultWebSecurityManager.setRealm(realm);
    return  defaultWebSecurityManager;
}
  • 創(chuàng)建自己的訪問數(shù)據(jù)庫域
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");//設(shè)置使用什么方式進(jìn)行加密
      hashedCredentialsMatcher.setHashIterations(1024);//設(shè)置散列的次數(shù)
      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());//設(shè)置認(rèn)證秘鑰md5+salt+散列
        //開啟緩存
        customRealm.setCachingEnabled(true);//開啟全局緩存
        customRealm.setCacheManager(ehCacheManager());
        customRealm.setAuthenticationCachingEnabled(true);//開啟認(rèn)證緩存
        customRealm.setAuthenticationCacheName("AuthenticationCache");//設(shè)置認(rèn)證緩存的名字
        customRealm.setAuthorizationCachingEnabled(true);//開啟授權(quán)緩存
        customRealm.setAuthorizationCacheName("AuthorizationCache");//設(shè)置授權(quán)緩存的名字
        customRealm.setCacheManager(new EhCacheManager());//設(shè)置緩存管理器
    
        return customRealm;
    }
    

shiro整合redis

  • 添加redis依賴

      <!--添加redis緩存配置-->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-redis</artifactId>
      </dependency>
    
  • redis實(shí)現(xiàn)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);
        }
    }
    
  • 設(shè)置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中設(shè)置redisCacheManager

      @Bean
      public CacheManager redisCacheManager(){
          return new RedisCacheShiroManager(redisTemplate);
      }
      /**
      * 自定義realm實(shí)現(xiàn)
      * 1氓涣、設(shè)置MD5加密驗(yàn)證機(jī)制
      * 2、開啟realm緩存
      * @return
      */
      @Bean
      public AuthorizingRealm getAuthorizingRealm(){
          CustomRealm customRealm = new CustomRealm();
          customRealm.setCredentialsMatcher(redentialsMatcher());//設(shè)置認(rèn)證秘鑰md5+salt+散列
          //開啟緩存
          customRealm.setCachingEnabled(true);//開啟全局緩存
          //customRealm.setCacheManager(ehCacheManager());
          customRealm.setCacheManager(redisCacheManager());
          customRealm.setAuthenticationCachingEnabled(true);//開啟認(rèn)證緩存
          customRealm.setAuthenticationCacheName("AuthenticationCache");//設(shè)置認(rèn)證緩存的名字
          customRealm.setAuthorizationCachingEnabled(true);//開啟授權(quán)緩存
          customRealm.setAuthorizationCacheName("AuthorizationCache");//設(shè)置授權(quán)緩存的名字
          customRealm.setCacheManager(new EhCacheManager());//設(shè)置緩存管理器
            return customRealm;
      }
    

shiro 集成驗(yàn)證碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末陋气,一起剝皮案震驚了整個(gè)濱河市劳吠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌巩趁,老刑警劉巖痒玩,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異议慰,居然都是意外死亡蠢古,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門别凹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來草讶,“玉大人,你說我怎么就攤上這事炉菲《檎剑” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵拍霜,是天一觀的道長嘱丢。 經(jīng)常有香客問我,道長沉御,這世上最難降的妖魔是什么屿讽? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮吠裆,結(jié)果婚禮上伐谈,老公的妹妹穿的比我還像新娘。我一直安慰自己试疙,他們只是感情好诵棵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著祝旷,像睡著了一般履澳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上怀跛,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天距贷,我揣著相機(jī)與錄音,去河邊找鬼吻谋。 笑死忠蝗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的漓拾。 我是一名探鬼主播阁最,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼戒祠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了速种?” 一聲冷哼從身側(cè)響起姜盈,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎配阵,沒想到半個(gè)月后馏颂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡棋傍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年饱亮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舍沙。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡近上,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拂铡,到底是詐尸還是另有隱情壹无,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布感帅,位于F島的核電站斗锭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏失球。R本人自食惡果不足惜岖是,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望实苞。 院中可真熱鬧豺撑,春花似錦、人聲如沸黔牵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽猾浦。三九已至陆错,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間金赦,已是汗流浹背音瓷。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留夹抗,地道東北人绳慎。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親偷线。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355