日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

志宇-shiro-web

發(fā)布時間:2024/3/26 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 志宇-shiro-web 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

shiro-web

  • Shiro的使用場景
  • Shiro的核心類
    • SecurityUtils
    • Subject
    • DefaultWebSecurityManager
      • 類圖如下
      • 類圖中每個類的作用
      • 主要方法
    • Shiro的攔截器主要類
      • DefaultFilter
      • shiroFilterFactoryBean
    • 一個自帶的攔截器類圖
    • Shiro的Filter配置路徑說明
    • Shiro配置Filter路徑
  • shiro注解注解使用
  • shiro緩存使用
      • 類圖如下
      • CachingRealm
      • AuthenticatingRealm
      • AuthorizingRelam
      • CacheManager
    • 會話管理
    • 密碼加密使用
      • 校驗密碼
      • 加密
  • 自學(xué)項目地址

Shiro的使用場景

在單機應(yīng)用集群部署環(huán)境時可以使用Shiro,因Shiro提供了相關(guān)持久化接口,底層寫好了將session持久化到redis數(shù)據(jù)庫
在微服務(wù)中不推薦使用shiro,因每個模塊都要權(quán)限校驗
Auth2.0: 用于微信端授權(quán)登錄
jwt: 用于sessionid的加密和解密技術(shù)

Shiro的核心類

SecurityUtils

用于 獲得 SecurityManager 和 Subject 對象
將這兩個對象從 ThreadLocal中獲取,或存放

Subject

這個對象主要用于一些權(quán)限校驗比如 hasRole、isAuthenticated、isRemembered、login、logout方法
Subject維護(hù)著兩個對象一個是SecurityManager,一個是Session
Subject校驗方法調(diào)用SecurityManager對象中的方法
Subject的Session對象維護(hù)著SessionManager對象

DefaultWebSecurityManager

這個類中有很多成員變量,它可以調(diào)用每個成員變量的主要方法,我們只要給這個類設(shè)置對應(yīng)的成員變量即可, 主要成員變量如下,

  • Realm 實現(xiàn) 認(rèn)證 和 授權(quán)兩個方法(realm中也維護(hù)了很多對象)
  • SubjectDAO 用于將Subject中的主要信息持久化
  • SubjectContext 用于創(chuàng)建Subject
  • SessionManager 會話管理
  • CacheManager 認(rèn)證和授權(quán)緩存的管理
  • Authorizer 授權(quán)對象
  • Authenticator 認(rèn)證對象
  • 類圖如下

    類圖中每個類的作用

    DefaultSecurityManager: 用來管理 RememberMeManager、SubjectDAO、SubjectFactory、SubjectContext 對象

    SessionsSecurityManager: 用來管理sessionManager對象

    AuthorizingSecurityManager: 用來管理Authorizer對象

    AuthenticatingSecurityManager: 用來管理Authenticator對象

    RealmSecurityManager: 用來管理Realm 對象

    CachingSecurityManager: 用來管理CacheManager、EventBus對象

    主要方法

    這個類主要使用的方法: login、logout、remember方法
    login 主要流程

    info = this.authenticate(token); ---》info = this.doAuthenticate(token); //獲得所有綁定的Realm,先上緩存找,如果緩存沒開或者沒找到則調(diào)用Relam的doGetAuthenticationInfo方法 --------this.assertCredentialsMatch(token, info);//查看是token是否匹配,調(diào)用Realm中CredentialsMatcher對象的doCredentialsMatch方法 ---this.notifySuccess(token, info);//這里是一個監(jiān)聽,調(diào)用AuthenticationListener對象的onSuccess方法 this.onFailedLogin(token, ae, subject); //登錄失敗調(diào)用這個方法 ---》rmm.onFailedLogin(subject, token, ex);//給客戶端設(shè)置一個登錄失敗的Cookie信息 response.addHeader("Set-Cookie", headerValue); Subject loggedIn = this.createSubject(token, info, subject); ---》SubjectContext context = this.createSubjectContext();//創(chuàng)建DefaultSubjectContext對象 ---this.createSubject(context); --------》context = this.ensureSecurityManager(context); --------------》context.setSecurityManager(this);//把SecurityManager設(shè)置給DefaultSubjectContext --------》context = this.resolveSession(context);//從MapContext的Map中獲得一個值,有值則通過 --------》context = this.resolvePrincipals(context);//將Principals設(shè)置給DefaultSubjectContext context.setPrincipals(principals); --------》Subject subject = this.doCreateSubject(context);//調(diào)用SubjectFactory接口實現(xiàn)類,創(chuàng)建Subject 返回一個WebDelegatingSubject對象 --------this.save(subject);//調(diào)用SubjectDAO接口實現(xiàn)類save方法存儲 Subject對象中的主要信息 --------------if (this.isSessionStorageEnabled(subject)) {this.saveToSession(subject);//獲得SessionStorageEvaluator接口實現(xiàn)類 調(diào)用isSessionStorageEnabled方法//當(dāng)情況允許的情況下 ----------------------this.mergePrincipals(subject);//將 principals 通過反射存放 DelegatingSubject字段中//將principals 放到session中//通過sessionDao 將信息持久化到數(shù)據(jù)庫或內(nèi)存 ----------------------this.mergeAuthenticationState(subject);//如果授權(quán)成功在sesison中放一個屬性,屬性值為true//通過sessionDao 將信息持久化到數(shù)據(jù)庫或內(nèi)存this.onSuccessfulLogin(token, info, loggedIn);//調(diào)用RememberMeManager 中的方法 rmm.onSuccessfulLogin(subject, token, info);

    logout 主要流程

    this.beforeLogout(subject);//調(diào)用RememberMeManager 的方法 rmm.onLogout(subject);//刷新Cookie ((LogoutAware)authc).onLogout(principals);//循環(huán)調(diào)用所有的AuthenticationListener執(zhí)行onLogout方法this.delete(subject);//subjectDAO.delete(subject); 刪除對應(yīng)的session//session.removeAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY);//session.removeAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);this.stopSession(subject); ---》Session s = subject.getSession(false);//獲得 DelegatingSubject(Subject)中的Session對象DelegatingSession ---》s.stop(); --------this.sessionManager.stop(this.key); --------------》Session session = this.lookupRequiredSession(key);--------------》session.stop(); --------------this.onStop(session, key); --------------this.notifyStop(session); --------------this.afterStopped(session);

    Shiro的攔截器主要類

    DefaultFilter

    shiro總共定義了11種攔截器,我只要配置這些攔截器會攔截那些路徑即可,當(dāng)我們有特殊需求時也可以自己自定義的攔截器進(jìn)行攔截

    public enum DefaultFilter {//匿名攔截器,不需要登錄即可訪問的資源,匿名用戶或游客,一般用于過濾靜態(tài)資源anon(AnonymousFilter.class),//需要認(rèn)證登錄才能訪問authc(FormAuthenticationFilter.class),//httpBasic 身份驗證攔截器authcBasic(BasicHttpAuthenticationFilter.class),//退出攔截器logout(LogoutFilter.class),noSessionCreation(NoSessionCreationFilter.class),//權(quán)限授權(quán)攔截器,驗證用戶是否擁有權(quán)限perms(PermissionsAuthorizationFilter.class),//配置哪些路徑 要固定端口才能訪問port(PortFilter.class),rest(HttpMethodPermissionFilter.class),//配置哪些路徑 要哪些角色才能訪問roles(RolesAuthorizationFilter.class),//配置哪些路徑 要https 訪問ssl(SslFilter.class),//用戶攔截器,表示必須存在用戶user(UserFilter.class);}

    shiroFilterFactoryBean

    shiroFilterFactoryBean實現(xiàn)了Spring中的FactoryBean、BeanPostProcessor
    實現(xiàn)FactoryBean接口說明,它可以給spring創(chuàng)建對象通過getObject()方法
    實現(xiàn)BeanPostProcessor接口,說明它是spring的一個后置處理器
    項目啟動時,后置處理器會在屬性賦值后,也就是spring每個對象初始化(spring的init方法)前后執(zhí)行
    這個類的主要作用就是獲得配置的自定義Filter和默認(rèn)的Filter以及要攔截url對象創(chuàng)建放到spring中
    在 getObject方法

    FilterChainManager manager = this.createFilterChainManager(); --》DefaultFilterChainManager manager = new DefaultFilterChainManager();//在DefaultFilterChainManager 創(chuàng)建一個Filter集合 和一個Filter鏈,//將DefaultFilter枚舉中的所有Filter放到集合中 --》Map<String, Filter> filters = this.getFilters(); --》manager.addFilter(name, filter, false)) //將自己定義的Filter放到集合中 --》manager.createChain(url, chainDefinition);//將Filter和url分別放到對應(yīng)的容器中

    在spring后置處理器的前置方法中

    if (bean instanceof Filter) { this.applyGlobalPropertiesIfNecessary(filter); this.getFilters().put(beanName, filter); }

    對所有Filter 進(jìn)行攔截,包裝下,然后將Filter放到shiroFilterFactoryBean中

    一個自帶的攔截器類圖


    NameableFilter:
    用來給這個Filter設(shè)置一個name
    OncePerRequestFilter:
    一個人不能在同時間執(zhí)行兩次這個方法,就好比上了一把鎖,方法執(zhí)行時候把鎖打開,執(zhí)行完打開鎖
    ,這里更新了sessionid的失效時間,同時執(zhí)行后面的filter
    AdviceFilter
    在執(zhí)行chain.doFilter(request, response);前后調(diào)用
    boolean continueChain = this.preHandle(request, response);
    //返回boolean類型,如果返回false則不繼續(xù)執(zhí)行
    this.postHandle(request, response); 交給子類去實現(xiàn)

    Shiro的Filter配置路徑說明

    路徑通配符支持 ?、*、**,注意通配符匹配不 包括目錄分隔符“/” 匹配說明 ? : 匹配一個字符,如 /user? , 匹配 /user3,但不匹配/user/; * : 匹配零個或多個字符串,如 /add* ,匹配 /addtest,但不匹配 /user/1 ** : 匹配路徑中的零個或多個路徑,如 /user/** 將匹 配 /user/xxx 或 /user/xxx/yyy 例子 /user/**=filter1 /user/add=filter2

    Shiro配置Filter路徑

    1、配置的信息要放到LinkedHashMap,否則 部分路徑無法進(jìn)行攔截,時有時無
    2、要按順序放到攔截器中,權(quán)限從小到大依次放入
    3、LinkedHashMap中第一個參數(shù)是 攔截路徑,第二個是攔截器名稱(名字在枚舉類DefaultFilter中)

    //攔截器路徑,坑一,部分路徑無法進(jìn)行攔截,時有時無;因為同學(xué)使用的是hashmap, 無序的,應(yīng)該改為LinkedHashMap Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();//退出過濾器 filterChainDefinitionMap.put("/logout","logout");//匿名可以訪問,也是就游客模式 filterChainDefinitionMap.put("/pub/**","anon");//登錄用戶才可以訪問 filterChainDefinitionMap.put("/authc/**","authc");//管理員角色才可以訪問 filterChainDefinitionMap.put("/admin/**","roleOrFilter[admin,root]");//有編輯權(quán)限才可以訪問 filterChainDefinitionMap.put("/video/update","perms[video_update]");//坑二: 過濾鏈?zhǔn)琼樞驁?zhí)行,從上而下//authc : url定義必須通過認(rèn)證才可以訪問 //anon : url可以匿名訪問 filterChainDefinitionMap.put("/**", "authc");

    shiro注解注解使用

    不推薦使用注解,springboot中要配置一些配置類,注解才能生效

    @RequiresRoles(value={"admin", "editor"}, logical= Logical.AND) 需要角色 admin 和 editor兩個角色 AND表示兩個同時成立@RequiresPermissions (value={"user:add", "user:del"}, logical= Logical.OR) 需要權(quán)限 user:add 或 user:del權(quán)限其中一個,OR是或的意思。@RequiresAuthentication 已經(jīng)授過權(quán),調(diào)用Subject.isAuthenticated()返回true@RequiresUser 身份驗證或者通過記 住我登錄的

    使用下面代碼替換

    subject.hasRole("xxx"); subject.isPermitted("xxx"); subject. isPermittedAll("xxxxx","yyyy"); subject.checkRole("xxx"); // 無返回值,可以認(rèn)為內(nèi)部使用斷言的方式

    shiro緩存使用

    可以將shiro的認(rèn)證和授權(quán)所得到的資源緩存起來
    緩存后再次使用資源就不會走Realm中的認(rèn)證和授權(quán)方法了

    類圖如下


    CachingRealm

    這個Realm主要起管理緩存對象,同時可以設(shè)置是否開啟緩存
    因?qū)崿F(xiàn)了CacheManagerAware接口,實現(xiàn)了setCacheManager方法,要在子類中注入CacheManager對象,所以CachingRealm封裝了CacheManager 類型的對象

    AuthenticatingRealm

    這個Relam是在認(rèn)證時起到緩存作用, AuthenticatingRealm在構(gòu)造方法中設(shè)置了

    this.authenticationCachingEnabled = false;

    代表默認(rèn) 認(rèn)證不會開啟緩存(因為不會頻繁登錄,用戶修改了密碼還要改緩存)

    AuthorizingRelam

    這個Relam是在授權(quán)時起到緩存作用, AuthorizingRelam在構(gòu)造方法中設(shè)置了

    this.authorizationCachingEnabled = true;

    代表默認(rèn) 授權(quán)會開啟緩存 (相對來說訪問較多,修改權(quán)限次數(shù)較少)

    CacheManager

    //它實現(xiàn)了CacheManager 同時是抽象的 可以通過繼承他重寫緩存主要方法 //它實現(xiàn)了InitializingBean 會在spring將對象發(fā)到ioc容器中后 調(diào)用(一般用于ioc容器對象中的成員變量賦值) public abstract class AbstractCacheManager implements CacheManager, InitializingBean {)

    CachingRealm中有用到CacheManager類型對象,用這個對象來指定如何緩存
    CacheManager是一個接口,抽象類AbstractCacheManager實現(xiàn)了 CacheManager
    如果自己寫不建議使用AbstractCacheManager類作為父類,因為它會將緩存信息放到Map中
    直接實現(xiàn)CacheManager接口即可,想緩存到redis中要導(dǎo)入如下依賴

    <!-- shiro+redis緩存插件 --><dependency><groupId>org.crazycake</groupId><artifactId>shiro-redis</artifactId><version>3.1.0</version></dependency>

    會提供一個RedisCacheManager對象,它實現(xiàn)了CacheManager接口
    RedisCacheManager中有一個成員變量 redisManager
    redisManager用來連接redis數(shù)據(jù)庫
    RedisCacheManager用來從redis中獲取數(shù)據(jù) (不能往redis中設(shè)置數(shù)據(jù),只能取)
    要想往Redis中設(shè)置數(shù)據(jù)要創(chuàng)建 redisSessionDao對象
    同時redisSessionDao對象要通過DefaultWebSessionManager 對象進(jìn)行綁定

    會話管理

    SessionManager
    start 開啟一個session
    getSession 通過sessionid獲得session

    DefaultWebSessionManager是SessionManager 類型的
    這個對象里面維護(hù)著 cacheManager 和 SessionDAO
    使用redis緩存sessionid的話 就將RedisSessionDAO對象設(shè)置給SessionDAO接口
    SessionDAO接口負(fù)責(zé)將sessionid緩存到指定數(shù)據(jù)庫
    如何自定義sessionid key的格式和value
    key要在 DefaultWebSessionManager 中進(jìn)行修改
    value 要在redisSessionDAO 的SessionIdGenerator 類修改

    密碼加密使用

    鹽值加密
    加密時候加點鹽就好了 (這個鹽可以是注冊時候 創(chuàng)建的放到用戶表中)

    校驗密碼

    首先要獲得輸入的密碼 和從數(shù)據(jù)庫加密的密碼
    我們要將輸入的密碼加密 然后和數(shù)據(jù)庫中的密碼比對
    如果我們想要自己定義方法,同時解密時候也要使用
    那么shiro要在哪里進(jìn)行校驗密碼呢?
    當(dāng)然是認(rèn)證環(huán)節(jié)了,也就是 AuthenticatingRealm 類了
    AuthenticatingRealm中有一個對象CredentialsMatcher 這個就是用來來加密的對象
    HashedCredentialsMatcher參數(shù)使用

    同時 在認(rèn)證時傳入?yún)?shù)中要傳入鹽

    加密

    在注冊密碼和修改密碼時進(jìn)行加密

    自學(xué)項目地址

    總結(jié)

    以上是生活随笔為你收集整理的志宇-shiro-web的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。