天天看點

【Shiro】Shiro從小白到大神(三)-權限認證(授權)權限認證源代碼下載下傳位址:

本節講權限認證,也就是授權

基于角色的通路控制和基于權限的通路控制的小執行個體

以及注解式授權和JSP标簽授權詳解

權限認證,也就是通路控制,即在應用中控制誰能通路哪些資源

在權限認證中,最核心的三個要素是:權限,角色和使用者 (資源也算一個要素,但不是最核心的)

權限,即操作資源的 權限,比如通路某個頁面,以及對某個子產品的資料的添加,修改,删除,檢視的權利(整合以後,其實就是一些對URL請求的權限)

角色,是權限的集合,一種角色可以包含多種權限(将權限賦給角色)

使用者,在Shiro中,代表通路系統的使用者,即Subject(将角色賦給使用者)

【Shiro】Shiro從小白到大神(三)-權限認證(授權)權限認證源代碼下載下傳位址:

首先配置ini檔案:

測試類

示範結果自己跑一遍就出來啦

配置ini檔案:

測試類:

講了幾個org.apache.shiro.subject.Subject的函數。

其實官方文檔都有介紹的

首先你的Java版本5+才能內建shiro的注解

RequiresAuthentication注解需要在目前會話中對目前的Subject進行身份驗證,以便通路或調用該注解的類/執行個體/方法。

也就是要求目前Subject已經在目前的Session中被驗證通過才能被通路或調用

比如:

基本等同于下面的代碼:

要求目前的Subject是一個’guest’(遊客),也就是說,必須是在之前的session中沒有被驗證或被記住才能被通路和調用

例如:

基本等價于下面的代碼:

RequiresPermissions注解要求目前Subject允許一個或多個權限來執行帶注釋的方法。

也就是說,必須有這個權限才能通路

基本等價于:

RequiresRoles注解要求目前Subject擁有所有指定的角色。如果它們沒有所有的角色,則不會執行該方法,并抛出AuthorizationException

基本等同于以下代碼:

RequiresUser注解 需要目前的Subject是一個應用程式的使用者 才能被所注解的類/執行個體/方法通路或者調用。

一個”應用程式使用者”被定義一個擁有已知身份,或在目前session中通過驗證被确認,或者在之前的session中的”RememberMe”服務被記住

也就是說,必須是某個使用者

基本等同于下面代碼:

必須添加shiro-web.jar

在jsp頁面中引入:

使用者沒有身份驗證時顯示相應資訊,即遊客通路資訊

在這裡标簽内的文字,如果使用者沒有登入才會顯示出來,也就是遊客

隻有在目前Subject被認為是“使用者”時,使用者标記才會顯示其包裝内容。

在這個上下文中,“使用者”被定義為一個具有已知身份的主題,要麼是成功的身份驗證,要麼是來自“記住我”的服務。

注意,這個标記與經過身份驗證的标記有語義上的不同,它比這個标記更加嚴格。

user标簽和guest标簽邏輯相反

僅當目前使用者在目前會話中成功驗證時才顯示正文内容。

它比“使用者”标簽更具限制性。它在邏輯上與“notAuthenticated”标記相反。

隻有在目前Subject在目前會話中成功驗證的情況下,經過身份驗證的标記才會顯示其包裝内容。

它是一個比使用者更嚴格的标記,用來保證敏感工作流中的辨別。也就是說,通過記住我登入的無法通路到!!!

如果目前Subject在目前會話中尚未成功驗證,則未驗證标記将顯示其包裝内容。

也就是使用者沒有身份驗證通過,即沒有調用Subject.login進行登入,包括記住我自動登入的也屬于未進行身份驗證這個notAuthenticated标簽!

輸出使用者資訊,會調用toString()方法

相當于調用以下代碼:

如果你不想擷取所有的,比如在使用者名和使用者id之間,我想擷取使用者id,可以通過下面這種方式:

等同于:

但是,當遇到複雜的情況時,上面的就不行了,畢竟可能不止一個Integer,這個時候就可以通過屬性名了。

通過getter方法擷取的

相當于下面的代碼:

或者說,可以結合type屬性:

也就是如下代碼的邏輯:

隻有當目前Subject被配置設定指定角色時,hasRole标記才會顯示其包裝内容

如果目前Subject沒有配置設定指定的角色,則将顯示其包裝内容。

lacksRole标簽與hasRole标簽的邏輯相反。

如果目前Subject從一個由逗号分隔的角色名稱清單中具有了任一指定的角色,那麼hasAnyRole标記将顯示其包裝内容。

隻要有其中一個角色,即顯示主體内容

如果目前Subject有權限則顯示其包裝的内容

如果目前Subject沒有該權限則顯示其包裝的内容

lacksPermission标簽與hasPermission标簽的邏輯相反

例如: queryPrinter權限-查詢權限

基本等同于:

第二種方式基本不用,用第一種方式即可

下面使用”:”用于分隔權限字元串下一部分的特殊字元。

即可配置多個權限

也可以用多值來配置:

驗證查詢權限:

比如我們有這些權限:

相當于:

使用第二種方法使用通配符比顯式地列出動作要更好,因為如果以後向應用程式添加了一個新操作,則不需要更新在該部分中使用通配符的權限。

還可以在通配符權限字元串的任何部分使用通配符令牌

所有資源的view權限

也就是說對“foo:view”(或其他的:view)的任何權限檢查将傳回true

通配符權限的另一個常見用法是建立執行個體級通路控制清單。

在這個權限中,您将使用三個部分——第一個是域,第二個是動作,第三個是被執行的執行個體(辨別)。

比如你擁有printer的query權限,列印機的id為lp7200,也就是擁有這類printer的query權限

如果您将這些權限授予使用者,那麼它們就可以在特定的執行個體上執行特定的行為。然後你可以在代碼中做一個檢查:

也就是說,具有所有printer的print權限,相當于前面的單個資源的多個權限

query和print之間用逗号隔開

在實際開發中,基本上用不到執行個體級别的權限控制

關于權限配置設定的最後一件事是:末尾丢失的部分意味着使用者可以通路與該部分對應的所有值。換句話說,

但是注意!

因為這不是末尾的*

雖然權限配置設定使用通配符構造相當多(“printer:*”=列印到任何printer),但在運作時的權限檢查應該始終基于可能的最特定的權限字元串。

比如:如果使用者有一個使用者界面,他們想要列印一個文檔到lp7200列印機,你應該檢查使用者是否允許執行這個代碼

這個檢查非常具體,并且明确地反映了使用者在那個時候正在嘗試做什麼。

但是,如下代碼是不對的:

因為第二個示例說“您必須能夠列印到任何列印機,以便執行以下代碼塊”。但請記住,“printer:print”等同于“printer:print:*”!

是以,這是一個不正确的檢查。

如果目前使用者沒有能力列印到任何列印機,但他們确實有列印的能力,比如lp7200和epsoncolor列印機。

然而,上面的第二個例子永遠不會允許他們列印到lp7200列印機,即使他們已經獲得了這種能力!

是以,經驗法則是在執行權限檢查時使用最特殊的權限字元串。

當然,如果您真的隻想執行代碼塊,如果使用者被允許列印到任何列印機(可能),那麼第二個方法可能是應用程式中的另一個有效的檢查。

您的應用程式将決定什麼檢查是有意義的,但是一般來說,越具體越好。

為什麼運作時權限檢查應該盡可能具體,但是權限配置設定可以更通用一些呢?

這是因為權限檢查是由隐含邏輯計算的,而不是平等檢查。

也就是說,如果使用者被配置設定給”user:“權限,這意味着使用者可以執行”user:view”操作。字元串”user:“顯然不等于”user:view”,但前者暗示後者。”user:*”描述了由”user:view”定義的功能的超集。

為了支援隐含規則,所有權限都被翻譯到實作org.apache.shiro.authz的對象執行個體的權限接口中。

這就是說,隐含邏輯可以在運作時執行,而且隐含邏輯通常比簡單的字元串等式檢查更複雜。

本文檔中描述的所有通配符行為實際上都是由org.apache.shiro.authz.permission.WildcardPermission類實作

下面是一些通配符的權限字元串,它顯示了通路的含義:

暗指還能删除使用者的能力:

但是:

也就是說,還可以使用執行個體12345更新使用者帳戶:

【Shiro】Shiro從小白到大神(三)-權限認證(授權)權限認證源代碼下載下傳位址:

授權其實就是檢視有沒有權限,有就授權給它

授權步驟:

歡迎轉載,分享是進步的源泉。