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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Apache Shiro 使用手册---转载

發(fā)布時(shí)間:2025/4/5 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Apache Shiro 使用手册---转载 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文地址:http://www.360doc.com/content/12/0104/13/834950_177177202.shtml

(一)Shiro架構(gòu)介紹

一、什么是Shiro?
Apache Shiro是一個(gè)強(qiáng)大易用的Java安全框架,提供了認(rèn)證、授權(quán)、加密和會(huì)話管理等功能:?
  • 認(rèn)證 - 用戶身份識(shí)別,常被稱為用戶“登錄”;
  • 授權(quán) - 訪問控制;
  • 密碼加密 - 保護(hù)或隱藏?cái)?shù)據(jù)防止被偷窺;
  • 會(huì)話管理 - 每用戶相關(guān)的時(shí)間敏感的狀態(tài)。

對(duì)于任何一個(gè)應(yīng)用程序,Shiro都可以提供全面的安全管理服務(wù)。并且相對(duì)于其他安全框架,Shiro要簡單的多。?

二、Shiro的架構(gòu)介紹?
首先,來了解一下Shiro的三個(gè)核心組件:Subject, SecurityManager 和 Realms. 如下圖:?
?
Subject:即“當(dāng)前操作用戶”。但是,在Shiro中,Subject這一概念并不僅僅指人,也可以是第三方進(jìn)程、后臺(tái)帳戶(Daemon Account)或其他類似事物。它僅僅意味著“當(dāng)前跟軟件交互的東西”。但考慮到大多數(shù)目的和用途,你可以把它認(rèn)為是Shiro的“用戶”概念。?
Subject代表了當(dāng)前用戶的安全操作,SecurityManager則管理所有用戶的安全操作。?

SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通過SecurityManager來管理內(nèi)部組件實(shí)例,并通過它來提供安全管理的各種服務(wù)。?

Realm: Realm充當(dāng)了Shiro與應(yīng)用安全數(shù)據(jù)間的“橋梁”或者“連接器”。也就是說,當(dāng)對(duì)用戶執(zhí)行認(rèn)證(登錄)和授權(quán)(訪問控制)驗(yàn)證時(shí),Shiro會(huì)從應(yīng)用配置的Realm中查找用戶及其權(quán)限信息。?
從這個(gè)意義上講,Realm實(shí)質(zhì)上是一個(gè)安全相關(guān)的DAO:它封裝了數(shù)據(jù)源的連接細(xì)節(jié),并在需要時(shí)將相關(guān)數(shù)據(jù)提供給Shiro。當(dāng)配置Shiro時(shí),你必須至少指定一個(gè)Realm,用于認(rèn)證和(或)授權(quán)。配置多個(gè)Realm是可以的,但是至少需要一個(gè)。?
Shiro內(nèi)置了可以連接大量安全數(shù)據(jù)源(又名目錄)的Realm,如LDAP、關(guān)系數(shù)據(jù)庫(JDBC)、類似INI的文本配置資源以及屬性文件等。如果缺省的Realm不能滿足需求,你還可以插入代表自定義數(shù)據(jù)源的自己的Realm實(shí)現(xiàn)。?


Shiro完整架構(gòu)圖:?

?
除前文所講Subject、SecurityManager 、Realm三個(gè)核心組件外,Shiro主要組件還包括:?
Authenticator :認(rèn)證就是核實(shí)用戶身份的過程。這個(gè)過程的常見例子是大家都熟悉的“用戶/密碼”組合。多數(shù)用戶在登錄軟件系統(tǒng)時(shí),通常提供自己的用戶名(當(dāng)事人)和支持他們的密碼(證書)。如果存儲(chǔ)在系統(tǒng)中的密碼(或密碼表示)與用戶提供的匹配,他們就被認(rèn)為通過認(rèn)證。?
Authorizer :授權(quán)實(shí)質(zhì)上就是訪問控制 - 控制用戶能夠訪問應(yīng)用中的哪些內(nèi)容,比如資源、Web頁面等等。?
SessionManager :在安全框架領(lǐng)域,Apache Shiro提供了一些獨(dú)特的東西:可在任何應(yīng)用或架構(gòu)層一致地使用Session API。即,Shiro為任何應(yīng)用提供了一個(gè)會(huì)話編程范式 - 從小型后臺(tái)獨(dú)立應(yīng)用到大型集群Web應(yīng)用。這意味著,那些希望使用會(huì)話的應(yīng)用開發(fā)者,不必被迫使用Servlet或EJB容器了。或者,如果正在使用這些容器,開發(fā)者現(xiàn)在也可以選擇使用在任何層統(tǒng)一一致的會(huì)話API,取代Servlet或EJB機(jī)制。?
CacheManager :對(duì)Shiro的其他組件提供緩存支持。

(二)Shiro 認(rèn)證

認(rèn)證就是驗(yàn)證用戶身份的過程。在認(rèn)證過程中,用戶需要提交實(shí)體信息(Principals)和憑據(jù)信息(Credentials)以檢驗(yàn)用戶是否合法。最常見的“實(shí)體/憑證”組合便是“用戶名/密碼”組合。?

一、Shiro認(rèn)證過程?

1、收集實(shí)體/憑據(jù)信息? Java代碼??
  • //Example?using?most?common?scenario?of?username/password?pair:???
  • UsernamePasswordToken?token?=?new?UsernamePasswordToken(username,?password); ??
  • //”Remember?Me”?built-in:???
  • token.setRememberMe(true);??
  • UsernamePasswordToken支持最常見的用戶名/密碼的認(rèn)證機(jī)制。同時(shí),由于它實(shí)現(xiàn)了RememberMeAuthenticationToken接口,我們可以通過令牌設(shè)置“記住我”的功能。?
    但是,“已記住”和“已認(rèn)證”是有區(qū)別的:?
    已記住的用戶僅僅是非匿名用戶,你可以通過subject.getPrincipals()獲取用戶信息。但是它并非是完全認(rèn)證通過的用戶,當(dāng)你訪問需要認(rèn)證用戶的功能時(shí),你仍然需要重新提交認(rèn)證信息。?
    這一區(qū)別可以參考亞馬遜網(wǎng)站,網(wǎng)站會(huì)默認(rèn)記住登錄的用戶,再次訪問網(wǎng)站時(shí),對(duì)于非敏感的頁面功能,頁面上會(huì)顯示記住的用戶信息,但是當(dāng)你訪問網(wǎng)站賬戶信息時(shí)仍然需要再次進(jìn)行登錄認(rèn)證。?

    2、提交實(shí)體/憑據(jù)信息?
    Java代碼??
  • Subject?currentUser?=?SecurityUtils.getSubject(); ??
  • currentUser.login(token);??
  • 收集了實(shí)體/憑據(jù)信息之后,我們可以通過SecurityUtils工具類,獲取當(dāng)前的用戶,然后通過調(diào)用login方法提交認(rèn)證。?

    3、認(rèn)證處理?
    Java代碼??
  • try?{ ??
  • ????currentUser.login(token); ??
  • }?catch?(?UnknownAccountException?uae?)?{?... ??
  • }?catch?(?IncorrectCredentialsException?ice?)?{?... ??
  • }?catch?(?LockedAccountException?lae?)?{?... ??
  • }?catch?(?ExcessiveAttemptsException?eae?)?{?... ??
  • }?...?catch?your?own?... ??
  • }?catch?(?AuthenticationException?ae?)?{ ??
  • ????//unexpected?error????
  • }??
  • 如果login方法執(zhí)行完畢且沒有拋出任何異常信息,那么便認(rèn)為用戶認(rèn)證通過。之后在應(yīng)用程序任意地方調(diào)用SecurityUtils.getSubject() 都可以獲取到當(dāng)前認(rèn)證通過的用戶實(shí)例,使用subject.isAuthenticated()判斷用戶是否已驗(yàn)證都將返回true.?
    相反,如果login方法執(zhí)行過程中拋出異常,那么將認(rèn)為認(rèn)證失敗。Shiro有著豐富的層次鮮明的異常類來描述認(rèn)證失敗的原因,如代碼示例。?

    二、登出操作?
    登出操作可以通過調(diào)用subject.logout()來刪除你的登錄信息,如:?
    Java代碼??
  • currentUser.logout();?//removes?all?identifying?information?and?invalidates?their?session?too.??
  • 當(dāng)執(zhí)行完登出操作后,Session信息將被清空,subject將被視作為匿名用戶。?

    三、認(rèn)證內(nèi)部處理機(jī)制?
    以上,是Shiro認(rèn)證在應(yīng)用程序中的處理過程,下面將詳細(xì)解說Shiro認(rèn)證的內(nèi)部處理機(jī)制。?
    ?

    如上圖,我們通過Shiro架構(gòu)圖的認(rèn)證部分,來說明Shiro認(rèn)證內(nèi)部的處理順序:?
    1、應(yīng)用程序構(gòu)建了一個(gè)終端用戶認(rèn)證信息的AuthenticationToken 實(shí)例后,調(diào)用Subject.login方法。?
    2、Sbuject的實(shí)例通常是DelegatingSubject類(或子類)的實(shí)例對(duì)象,在認(rèn)證開始時(shí),會(huì)委托應(yīng)用程序設(shè)置的securityManager實(shí)例調(diào)用securityManager.login(token)方法。?
    3、SecurityManager接受到token(令牌)信息后會(huì)委托內(nèi)置的Authenticator的實(shí)例(通常都是ModularRealmAuthenticator類的實(shí)例)調(diào)用authenticator.authenticate(token). ModularRealmAuthenticator在認(rèn)證過程中會(huì)對(duì)設(shè)置的一個(gè)或多個(gè)Realm實(shí)例進(jìn)行適配,它實(shí)際上為Shiro提供了一個(gè)可拔插的認(rèn)證機(jī)制。?
    4、如果在應(yīng)用程序中配置了多個(gè)Realm,ModularRealmAuthenticator會(huì)根據(jù)配置的AuthenticationStrategy(認(rèn)證策略)來進(jìn)行多Realm的認(rèn)證過程。在Realm被調(diào)用后,AuthenticationStrategy將對(duì)每一個(gè)Realm的結(jié)果作出響應(yīng)。?
    注:如果應(yīng)用程序中僅配置了一個(gè)Realm,Realm將被直接調(diào)用而無需再配置認(rèn)證策略。?
    5、判斷每一個(gè)Realm是否支持提交的token,如果支持,Realm將調(diào)用getAuthenticationInfo(token); getAuthenticationInfo 方法就是實(shí)際認(rèn)證處理,我們通過覆蓋Realm的doGetAuthenticationInfo方法來編寫我們自定義的認(rèn)證處理。?

    四、使用多個(gè)Realm的處理機(jī)制:?

    1、Authenticator?
    默認(rèn)實(shí)現(xiàn)是ModularRealmAuthenticator,它既支持單一Realm也支持多個(gè)Realm。如果僅配置了一個(gè)Realm,ModularRealmAuthenticator 會(huì)直接調(diào)用該Realm處理認(rèn)證信息,如果配置了多個(gè)Realm,它會(huì)根據(jù)認(rèn)證策略來適配Realm,找到合適的Realm執(zhí)行認(rèn)證信息。?
    自定義Authenticator的配置:?
    Java代碼??
  • [main] ??
  • ... ??
  • authenticator?=?com.foo.bar.CustomAuthenticator ??
  • securityManager.authenticator?=?$authenticator??

  • 2、AuthenticationStrategy(認(rèn)證策略)?
    當(dāng)應(yīng)用程序配置了多個(gè)Realm時(shí),ModularRealmAuthenticator將根據(jù)認(rèn)證策略來判斷認(rèn)證成功或是失敗。?
    例如,如果只有一個(gè)Realm驗(yàn)證成功,而其他Realm驗(yàn)證失敗,那么這次認(rèn)證是否成功呢?如果大多數(shù)的Realm驗(yàn)證成功了,認(rèn)證是否就認(rèn)為成功呢?或者,一個(gè)Realm驗(yàn)證成功后,是否還需要判斷其他Realm的結(jié)果?認(rèn)證策略就是根據(jù)應(yīng)用程序的需要對(duì)這些問題作出決斷。?
    認(rèn)證策略是一個(gè)無狀態(tài)的組件,在認(rèn)證過程中會(huì)經(jīng)過4次的調(diào)用:?
    • 在所有Realm被調(diào)用之前
    • 在調(diào)用Realm的getAuthenticationInfo 方法之前
    • 在調(diào)用Realm的getAuthenticationInfo 方法之后
    • 在所有Realm被調(diào)用之后
    認(rèn)證策略的另外一項(xiàng)工作就是聚合所有Realm的結(jié)果信息封裝至一個(gè)AuthenticationInfo實(shí)例中,并將此信息返回,以此作為Subject的身份信息。?
    Shiro有3中認(rèn)證策略的具體實(shí)現(xiàn):?
    AtLeastOneSuccessfulStrategy只要有一個(gè)(或更多)的Realm驗(yàn)證成功,那么認(rèn)證將被視為成功
    FirstSuccessfulStrategy第一個(gè)Realm驗(yàn)證成功,整體認(rèn)證將被視為成功,且后續(xù)Realm將被忽略
    AllSuccessfulStrategy所有Realm成功,認(rèn)證才視為成功

    ModularRealmAuthenticator 內(nèi)置的認(rèn)證策略默認(rèn)實(shí)現(xiàn)是AtLeastOneSuccessfulStrategy 方式,因?yàn)檫@種方式也是被廣泛使用的一種認(rèn)證策略。當(dāng)然,你也可以通過配置文件定義你需要的策略,如:?
    Java代碼??
  • [main] ??
  • ... ??
  • authcStrategy?=?org.apache.shiro.authc.pam.FirstSuccessfulStrategy ??
  • securityManager.authenticator.authenticationStrategy?=?$authcStrategy ??
  • ...??

  • 3、Realm的順序?
    由剛才提到的認(rèn)證策略,可以看到Realm在ModularRealmAuthenticator 里面的順序?qū)φJ(rèn)證是有影響的。?
    ModularRealmAuthenticator 會(huì)讀取配置在SecurityManager里的Realm。當(dāng)執(zhí)行認(rèn)證是,它會(huì)遍歷Realm集合,對(duì)所有支持提交的token的Realm調(diào)用getAuthenticationInfo 。?
    因此,如果Realm的順序?qū)δ闶褂玫恼J(rèn)證策略結(jié)果有影響,那么你應(yīng)該在配置文件中明確定義Realm的順序,如:?
    Java代碼??
  • blahRealm?=?com.company.blah.Realm ??
  • ... ??
  • fooRealm?=?com.company.foo.Realm ??
  • ... ??
  • barRealm?=?com.company.another.Realm ??
  • ??
  • securityManager.realms?=?$fooRealm,?$barRealm,?$blahRealm??
  • (三)Shiro 授權(quán)

    授權(quán)即訪問控制,它將判斷用戶在應(yīng)用程序中對(duì)資源是否擁有相應(yīng)的訪問權(quán)限。?
    如,判斷一個(gè)用戶有查看頁面的權(quán)限,編輯數(shù)據(jù)的權(quán)限,擁有某一按鈕的權(quán)限,以及是否擁有打印的權(quán)限等等。?

    一、授權(quán)的三要素?

    授權(quán)有著三個(gè)核心元素:權(quán)限、角色和用戶。?

    權(quán)限?
    權(quán)限是Apache Shiro安全機(jī)制最核心的元素。它在應(yīng)用程序中明確聲明了被允許的行為和表現(xiàn)。一個(gè)格式良好好的權(quán)限聲明可以清晰表達(dá)出用戶對(duì)該資源擁有的權(quán)限。?
    大多數(shù)的資源會(huì)支持典型的CRUD操作(create,read,update,delete),但是任何操作建立在特定的資源上才是有意義的。因此,權(quán)限聲明的根本思想就是建立在資源以及操作上。?
    而我們通過權(quán)限聲明僅僅能了解這個(gè)權(quán)限可以在應(yīng)用程序中做些什么,而不能確定誰擁有此權(quán)限。?
    于是,我們就需要在應(yīng)用程序中對(duì)用戶和權(quán)限建立關(guān)聯(lián)。?
    通常的做法就是將權(quán)限分配給某個(gè)角色,然后將這個(gè)角色關(guān)聯(lián)一個(gè)或多個(gè)用戶。?

    權(quán)限聲明及粒度?
    Shiro權(quán)限聲明通常是使用以冒號(hào)分隔的表達(dá)式。就像前文所講,一個(gè)權(quán)限表達(dá)式可以清晰的指定資源類型,允許的操作,可訪問的數(shù)據(jù)。同時(shí),Shiro權(quán)限表達(dá)式支持簡單的通配符,可以更加靈活的進(jìn)行權(quán)限設(shè)置。?
    下面以實(shí)例來說明權(quán)限表達(dá)式。?
    可查詢用戶數(shù)據(jù)?
    User:view?
    可查詢或編輯用戶數(shù)據(jù)?
    User:view,edit?
    可對(duì)用戶數(shù)據(jù)進(jìn)行所有操作?
    User:* 或 user?
    可編輯id為123的用戶數(shù)據(jù)?
    User:edit:123?

    角色?
    Shiro支持兩種角色模式:?
    1、傳統(tǒng)角色:一個(gè)角色代表著一系列的操作,當(dāng)需要對(duì)某一操作進(jìn)行授權(quán)驗(yàn)證時(shí),只需判斷是否是該角色即可。這種角色權(quán)限相對(duì)簡單、模糊,不利于擴(kuò)展。?
    2、權(quán)限角色:一個(gè)角色擁有一個(gè)權(quán)限的集合。授權(quán)驗(yàn)證時(shí),需要判斷當(dāng)前角色是否擁有該權(quán)限。這種角色權(quán)限可以對(duì)該角色進(jìn)行詳細(xì)的權(quán)限描述,適合更復(fù)雜的權(quán)限設(shè)計(jì)。?
    下面將詳細(xì)描述對(duì)兩種角色模式的授權(quán)實(shí)現(xiàn)。?

    二、授權(quán)實(shí)現(xiàn)?

    Shiro支持三種方式實(shí)現(xiàn)授權(quán)過程:?
    • 編碼實(shí)現(xiàn)
    • 注解實(shí)現(xiàn)
    • JSP Taglig實(shí)現(xiàn)
    1、基于編碼的授權(quán)實(shí)現(xiàn)?

    1.1基于傳統(tǒng)角色授權(quán)實(shí)現(xiàn)?
    當(dāng)需要驗(yàn)證用戶是否擁有某個(gè)角色時(shí),可以調(diào)用Subject 實(shí)例的hasRole*方法驗(yàn)證。?
    Java代碼??
  • Subject?currentUser?=?SecurityUtils.getSubject(); ??
  • if?(currentUser.hasRole("administrator"))?{ ??
  • ????//show?the?admin?button???
  • }?else?{ ??
  • ????//don't?show?the?button???Grey?it?out????
  • }??

  • 相關(guān)驗(yàn)證方法如下:?
    Subject方法描述
    hasRole(String roleName)當(dāng)用戶擁有指定角色時(shí),返回true
    hasRoles(List<String> roleNames)按照列表順序返回相應(yīng)的一個(gè)boolean值數(shù)組
    hasAllRoles(Collection<String> roleNames)如果用戶擁有所有指定角色時(shí),返回true

    斷言支持?
    Shiro還支持以斷言的方式進(jìn)行授權(quán)驗(yàn)證。斷言成功,不返回任何值,程序繼續(xù)執(zhí)行;斷言失敗時(shí),將拋出異常信息。使用斷言,可以使我們的代碼更加簡潔。?
    Java代碼??
  • Subject?currentUser?=?SecurityUtils.getSubject(); ??
  • //guarantee?that?the?current?user?is?a?bank?teller?and???
  • //therefore?allowed?to?open?the?account:???
  • currentUser.checkRole("bankTeller"); ??
  • openBankAccount();??

  • 斷言的相關(guān)方法:?
    Subject方法描述
    checkRole(String roleName)斷言用戶是否擁有指定角色
    checkRoles(Collection<String> roleNames)斷言用戶是否擁有所有指定角色
    checkRoles(String... roleNames)對(duì)上一方法的方法重載

    1.2 基于權(quán)限角色授權(quán)實(shí)現(xiàn)?
    相比傳統(tǒng)角色模式,基于權(quán)限的角色模式耦合性要更低些,它不會(huì)因角色的改變而對(duì)源代碼進(jìn)行修改,因此,基于權(quán)限的角色模式是更好的訪問控制方式。?
    它的代碼實(shí)現(xiàn)有以下幾種實(shí)現(xiàn)方式:?
    1、基于權(quán)限對(duì)象的實(shí)現(xiàn)?
    創(chuàng)建org.apache.shiro.authz.Permission的實(shí)例,將該實(shí)例對(duì)象作為參數(shù)傳遞給Subject.isPermitted()進(jìn)行驗(yàn)證。?
    Java代碼??
  • Permission?printPermission?=?new?PrinterPermission("laserjet4400n",?"print"); ??
  • Subject?currentUser?=?SecurityUtils.getSubject(); ??
  • if?(currentUser.isPermitted(printPermission))?{ ??
  • ????//show?the?Print?button???
  • }?else?{ ??
  • ????//don't?show?the?button???Grey?it?out????
  • } ??
  • Permission?printPermission?=?new?PrinterPermission("laserjet4400n",?"print"); ??
  • Subject?currentUser?=?SecurityUtils.getSubject(); ??
  • if?(currentUser.isPermitted(printPermission))?{ ??
  • ????//show?the?Print?button???
  • }?else?{ ??
  • ????//don't?show?the?button???Grey?it?out????
  • }??

  • 相關(guān)方法如下:?
    Subject方法描述
    isPermitted(Permission p)Subject擁有制定權(quán)限時(shí),返回treu
    isPermitted(List<Permission> perms)返回對(duì)應(yīng)權(quán)限的boolean數(shù)組
    isPermittedAll(Collection<Permission> perms)Subject擁有所有制定權(quán)限時(shí),返回true

    2、 基于字符串的實(shí)現(xiàn)?
    相比笨重的基于對(duì)象的實(shí)現(xiàn)方式,基于字符串的實(shí)現(xiàn)便顯得更加簡潔。?
    Java代碼??
  • Subject?currentUser?=?SecurityUtils.getSubject(); ??
  • if?(currentUser.isPermitted("printer:print:laserjet4400n"))?{ ??
  • ????//show?the?Print?button???
  • }?else?{ ??
  • ????//don't?show?the?button???Grey?it?out????
  • }??

  • 使用冒號(hào)分隔的權(quán)限表達(dá)式是org.apache.shiro.authz.permission.WildcardPermission 默認(rèn)支持的實(shí)現(xiàn)方式。?
    這里分別代表了 資源類型:操作:資源ID?

    類似基于對(duì)象的實(shí)現(xiàn)相關(guān)方法,基于字符串的實(shí)現(xiàn)相關(guān)方法:?
    isPermitted(String perm)、isPermitted(String... perms)、isPermittedAll(String... perms)?

    基于權(quán)限對(duì)象的斷言實(shí)現(xiàn)?
    Java代碼??
  • Subject?currentUser?=?SecurityUtils.getSubject(); ??
  • //guarantee?that?the?current?user?is?permitted???
  • //to?open?a?bank?account:???
  • Permission?p?=?new?AccountPermission("open"); ??
  • currentUser.checkPermission(p); ??
  • openBankAccount();??

  • 基于字符串的斷言實(shí)現(xiàn)?
    Java代碼??
  • Subject?currentUser?=?SecurityUtils.getSubject(); ??
  • //guarantee?that?the?current?user?is?permitted???
  • //to?open?a?bank?account:???
  • currentUser.checkPermission("account:open"); ??
  • openBankAccount();??

  • 斷言實(shí)現(xiàn)的相關(guān)方法?
    Subject方法說明
    checkPermission(Permission p)斷言用戶是否擁有制定權(quán)限
    checkPermission(String perm)斷言用戶是否擁有制定權(quán)限
    checkPermissions(Collection<Permission> perms)斷言用戶是否擁有所有指定權(quán)限
    checkPermissions(String... perms)斷言用戶是否擁有所有指定權(quán)限

    2、基于注解的授權(quán)實(shí)現(xiàn)?
    Shiro注解支持AspectJ、Spring、Google-Guice等,可根據(jù)應(yīng)用進(jìn)行不同的配置。?

    相關(guān)的注解:?
    @ RequiresAuthentication?
    可以用戶類/屬性/方法,用于表明當(dāng)前用戶需是經(jīng)過認(rèn)證的用戶。?
    Java代碼??
  • @RequiresAuthentication??
  • public?void?updateAccount(Account?userAccount)?{ ??
  • ????//this?method?will?only?be?invoked?by?a????
  • ????//Subject?that?is?guaranteed?authenticated???
  • ????... ??
  • }??

  • @ RequiresGuest?
    表明該用戶需為”guest”用戶?

    @ RequiresPermissions?
    當(dāng)前用戶需擁有制定權(quán)限?
    Java代碼??
  • @RequiresPermissions("account:create") ??
  • public?void?createAccount(Account?account)?{ ??
  • ????//this?method?will?only?be?invoked?by?a?Subject???
  • ????//that?is?permitted?to?create?an?account???
  • ????... ??
  • }??

  • @RequiresRoles?
    當(dāng)前用戶需擁有制定角色?

    @ RequiresUser?
    當(dāng)前用戶需為已認(rèn)證用戶或已記住用戶?

    3、基于JSP? TAG的授權(quán)實(shí)現(xiàn)?
    Shiro提供了一套JSP標(biāo)簽庫來實(shí)現(xiàn)頁面級(jí)的授權(quán)控制。?
    在使用Shiro標(biāo)簽庫前,首先需要在JSP引入shiro標(biāo)簽:?
    Java代碼??
  • <%@?taglib?prefix="shiro"?uri="http://shiro.apache.org/tags"?%>??

  • 下面一一介紹Shiro的標(biāo)簽:?
    guest標(biāo)簽?
    驗(yàn)證當(dāng)前用戶是否為“訪客”,即未認(rèn)證(包含未記住)的用戶?
    Xml代碼??
  • <shiro:guest>??
  • ????Hi?there!??Please?<a?href="login.jsp">Login</a>?or?<a?href="signup.jsp">Signup</a>?today! ??
  • </shiro:guest>??

  • user標(biāo)簽?
    認(rèn)證通過或已記住的用戶?
    Xml代碼??
  • <shiro:user>??
  • ????Welcome?back?John!??Not?John??Click?<a?href="login.jsp">here<a>?to?login. ??
  • </shiro:user>??

  • authenticated標(biāo)簽?
    已認(rèn)證通過的用戶。不包含已記住的用戶,這是與user標(biāo)簽的區(qū)別所在。?
    Xml代碼??
  • <shiro:authenticated>??
  • ????<a?href="updateAccount.jsp">Update?your?contact?information</a>. ??
  • </shiro:authenticated>??

  • notAuthenticated標(biāo)簽?
    未認(rèn)證通過用戶,與authenticated標(biāo)簽相對(duì)應(yīng)。與guest標(biāo)簽的區(qū)別是,該標(biāo)簽包含已記住用戶。?
    Xml代碼??
  • <shiro:notAuthenticated>??
  • ????Please?<a?href="login.jsp">login</a>?in?order?to?update?your?credit?card?information. ??
  • </shiro:notAuthenticated>??

  • principal 標(biāo)簽?
    輸出當(dāng)前用戶信息,通常為登錄帳號(hào)信息?
    Xml代碼??
  • Hello,?<shiro:principal/>,?how?are?you?today???

  • hasRole標(biāo)簽?
    驗(yàn)證當(dāng)前用戶是否屬于該角色?
    Xml代碼??
  • <shiro:hasRole?name="administrator">??
  • ????<a?href="admin.jsp">Administer?the?system</a>??
  • </shiro:hasRole>??

  • lacksRole標(biāo)簽?
    與hasRole標(biāo)簽邏輯相反,當(dāng)用戶不屬于該角色時(shí)驗(yàn)證通過?
    Xml代碼??
  • <shiro:lacksRole?name="administrator">??
  • ????Sorry,?you?are?not?allowed?to?administer?the?system. ??
  • </shiro:lacksRole>??

  • hasAnyRole標(biāo)簽?
    驗(yàn)證當(dāng)前用戶是否屬于以下任意一個(gè)角色。?
    Xml代碼??
  • <shiro:hasAnyRoles?name="developer,?project?manager,?administrator">??
  • ????You?are?either?a?developer,?project?manager,?or?administrator. ??
  • </shiro:lacksRole>??

  • hasPermission標(biāo)簽?
    驗(yàn)證當(dāng)前用戶是否擁有制定權(quán)限?
    Xml代碼??
  • <shiro:hasPermission?name="user:create">??
  • ????<a?href="createUser.jsp">Create?a?new?User</a>??
  • </shiro:hasPermission>??

  • lacksPermission標(biāo)簽?
    與hasPermission標(biāo)簽邏輯相反,當(dāng)前用戶沒有制定權(quán)限時(shí),驗(yàn)證通過?
    Xml代碼??
  • <shiro:hasPermission?name="user:create">??
  • ????<a?href="createUser.jsp">Create?a?new?User</a>??
  • </shiro:hasPermission>??


  • 三、Shiro授權(quán)的內(nèi)部處理機(jī)制?
    ?
    1、在應(yīng)用程序中調(diào)用授權(quán)驗(yàn)證方法(Subject的isPermitted*或hasRole*等)?
    2、Sbuject的實(shí)例通常是DelegatingSubject類(或子類)的實(shí)例對(duì)象,在認(rèn)證開始時(shí),會(huì)委托應(yīng)用程序設(shè)置的securityManager實(shí)例調(diào)用相應(yīng)的isPermitted*或hasRole*方法。?
    3、接下來SecurityManager會(huì)委托內(nèi)置的Authorizer的實(shí)例(默認(rèn)是ModularRealmAuthorizer 類的實(shí)例,類似認(rèn)證實(shí)例,它同樣支持一個(gè)或多個(gè)Realm實(shí)例認(rèn)證)調(diào)用相應(yīng)的授權(quán)方法。?
    4、每一個(gè)Realm將檢查是否實(shí)現(xiàn)了相同的 Authorizer 接口。然后,將調(diào)用Reaml自己的相應(yīng)的授權(quán)驗(yàn)證方法。?

    當(dāng)使用多個(gè)Realm時(shí),不同于認(rèn)證策略處理方式,授權(quán)處理過程中:?
    1、當(dāng)調(diào)用Realm出現(xiàn)異常時(shí),將立即拋出異常,結(jié)束授權(quán)驗(yàn)證。?
    2、只要有一個(gè)Realm驗(yàn)證成功,那么將認(rèn)為授權(quán)成功,立即返回,結(jié)束認(rèn)證。

    (四)Realm 實(shí)現(xiàn)

    在認(rèn)證、授權(quán)內(nèi)部實(shí)現(xiàn)機(jī)制中都有提到,最終處理都將交給Real進(jìn)行處理。因?yàn)樵赟hiro中,最終是通過Realm來獲取應(yīng)用程序中的用戶、角色及權(quán)限信息的。通常情況下,在Realm中會(huì)直接從我們的數(shù)據(jù)源中獲取Shiro需要的驗(yàn)證信息。可以說,Realm是專用于安全框架的DAO.?

    一、認(rèn)證實(shí)現(xiàn)?
    正如前文所提到的,Shiro的認(rèn)證過程最終會(huì)交由Realm執(zhí)行,這時(shí)會(huì)調(diào)用Realm的getAuthenticationInfo(token)方法。?
    該方法主要執(zhí)行以下操作:?
    1、檢查提交的進(jìn)行認(rèn)證的令牌信息?
    2、根據(jù)令牌信息從數(shù)據(jù)源(通常為數(shù)據(jù)庫)中獲取用戶信息?
    3、對(duì)用戶信息進(jìn)行匹配驗(yàn)證。?
    4、驗(yàn)證通過將返回一個(gè)封裝了用戶信息的AuthenticationInfo實(shí)例。?
    5、驗(yàn)證失敗則拋出AuthenticationException異常信息。?

    而在我們的應(yīng)用程序中要做的就是自定義一個(gè)Realm類,繼承AuthorizingRealm抽象類,重載doGetAuthenticationInfo (),重寫獲取用戶信息的方法。?
    Java代碼??
  • protected?AuthenticationInfo?doGetAuthenticationInfo(AuthenticationToken?authcToken)?throws?AuthenticationException?{ ??
  • ????????UsernamePasswordToken?token?=?(UsernamePasswordToken)?authcToken; ??
  • ????????User?user?=?accountManager.findUserByUserName(token.getUsername()); ??
  • ????????if?(user?!=?null)?{ ??
  • ????????????return?new?SimpleAuthenticationInfo(user.getUserName(),?user.getPassword(),?getName()); ??
  • ????????}?else?{ ??
  • ????????????return?null; ??
  • ????????} ??
  • }??

  • 二、授權(quán)實(shí)現(xiàn)?
    而授權(quán)實(shí)現(xiàn)則與認(rèn)證實(shí)現(xiàn)非常相似,在我們自定義的Realm中,重載doGetAuthorizationInfo()方法,重寫獲取用戶權(quán)限的方法即可。?
    Java代碼??
  • protected?AuthorizationInfo?doGetAuthorizationInfo(PrincipalCollection?principals)?{ ??
  • ????????String?userName?=?(String)?principals.fromRealm(getName()).iterator().next(); ??
  • ????????User?user?=?accountManager.findUserByUserName(userName); ??
  • ????????if?(user?!=?null)?{ ??
  • ????????????SimpleAuthorizationInfo?info?=?new?SimpleAuthorizationInfo(); ??
  • ????????????for?(Group?group?:?user.getGroupList())?{ ??
  • ????????????????info.addStringPermissions(group.getPermissionList()); ??
  • ????????????} ??
  • ????????????return?info; ??
  • ????????}?else?{ ??
  • ????????????return?null; ??
  • ????????} ??
  • }??
  • (五)Shiro 配置說明

    Apache Shiro的配置主要分為四部分:?
    • 對(duì)象和屬性的定義與配置
    • URL的過濾器配置
    • 靜態(tài)用戶配置
    • 靜態(tài)角色配置
    其中,由于用戶、角色一般由后臺(tái)進(jìn)行操作的動(dòng)態(tài)數(shù)據(jù),因此Shiro配置一般僅包含前兩項(xiàng)的配置。?

    Apache Shiro的大多數(shù)組件是基于POJO的,因此我們可以使用POJO兼容的任何配置機(jī)制進(jìn)行配置,例如:Java代碼、Sping XML、YAML、JSON、ini文件等等。下面,以Spring XML的配置方式為例,并且對(duì)其中的一些配置參數(shù)進(jìn)行一些簡單說明。?

    Shiro對(duì)象的配置:?
    主要是對(duì)Shiro各個(gè)組件的實(shí)現(xiàn)進(jìn)行定義配置,主要組件在前文已做過簡單介紹,這里不再一一說明。?
    Xml代碼??
  • <bean?id="securityManager"?class="org.apache.shiro.mgt.DefaultSecurityManager">??
  • ????????<property?name="cacheManager"?ref="cacheManager"/>??
  • ????????<property?name="sessionMode"?value="native"/>??
  • ????????<!--?Single?realm?app.??If?you?have?multiple?realms,?use?the?'realms'?property?instead.?-->??
  • ????????<property?name="realm"?ref="myRealm"/>??
  • ????????<property?name="sessionManager"?ref="sessionManager"/>? ??
  • </bean>??


  • Shiro過濾器的配置?
    Shiro主要是通過URL過濾來進(jìn)行安全管理,這里的配置便是指定具體授權(quán)規(guī)則定義。?
    Xml代碼??
  • <bean?id="shiroFilter"?class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">??
  • ????<property?name="securityManager"?ref="securityManager"/>??
  • ????<property?name="loginUrl"?value="/login.jsp"/>??
  • ????<property?name="successUrl"?value="/home.jsp"/>??
  • ????<property?name="unauthorizedUrl"?value="/unauthorized.jsp"/>?-->??
  • ????<property?name="filterChainDefinitions">??
  • ????????<value>??
  • ????????????#?some?example?chain?definitions: ??
  • ????????????/admin/**?=?authc,?roles[admin] ??
  • ????????????/docs/**?=?authc,?perms[document:read] ??
  • ????????????/**?=?authc ??
  • ????????????#?more?URL-to-FilterChain?definitions?here ??
  • ????????</value>??
  • ????</property>??
  • </bean>??

  • URL過濾器配置說明:?
    Shiro可以通過配置文件實(shí)現(xiàn)基于URL的授權(quán)驗(yàn)證。FilterChain定義格式:?
    URL_Ant_Path_Expression = Path_Specific_Filter_Chain?
    每個(gè)URL配置,表示匹配該URL的應(yīng)用程序請(qǐng)求將由對(duì)應(yīng)的過濾器進(jìn)行驗(yàn)證。?
    例如:?
    [urls]?
    /index.html = anon?
    /user/create = anon?
    /user/** = authc?
    /admin/** = authc, roles[administrator]?
    /rest/** = authc, rest?
    /remoting/rpc/** = authc, perms["remote:invoke"]?

    URL表達(dá)式說明?
    1、URL目錄是基于HttpServletRequest.getContextPath()此目錄設(shè)置?
    2、URL可使用通配符,**代表任意子目錄?
    3、Shiro驗(yàn)證URL時(shí),URL匹配成功便不再繼續(xù)匹配查找。所以要注意配置文件中的URL順序,尤其在使用通配符時(shí)。?

    Filter Chain定義說明?
    1、一個(gè)URL可以配置多個(gè)Filter,使用逗號(hào)分隔?
    2、當(dāng)設(shè)置多個(gè)過濾器時(shí),全部驗(yàn)證通過,才視為通過?
    3、部分過濾器可指定參數(shù),如perms,roles?

    Shiro內(nèi)置的FilterChain?
    Filter NameClass
    anonorg.apache.shiro.web.filter.authc.AnonymousFilter
    authcorg.apache.shiro.web.filter.authc.FormAuthenticationFilter
    authcBasicorg.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
    permsorg.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
    portorg.apache.shiro.web.filter.authz.PortFilter
    restorg.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
    rolesorg.apache.shiro.web.filter.authz.RolesAuthorizationFilter
    sslorg.apache.shiro.web.filter.authz.SslFilter
    userorg.apache.shiro.web.filter.authc.UserFilter

    總結(jié)

    以上是生活随笔為你收集整理的Apache Shiro 使用手册---转载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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