本節講權限認證,也就是授權
基于角色的通路控制和基于權限的通路控制的小執行個體
以及注解式授權和JSP标簽授權詳解
權限認證,也就是通路控制,即在應用中控制誰能通路哪些資源
在權限認證中,最核心的三個要素是:權限,角色和使用者 (資源也算一個要素,但不是最核心的)
權限,即操作資源的 權限,比如通路某個頁面,以及對某個子產品的資料的添加,修改,删除,檢視的權利(整合以後,其實就是一些對URL請求的權限)
角色,是權限的集合,一種角色可以包含多種權限(将權限賦給角色)
使用者,在Shiro中,代表通路系統的使用者,即Subject(将角色賦給使用者)
首先配置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更新使用者帳戶:
授權其實就是檢視有沒有權限,有就授權給它
授權步驟:
歡迎轉載,分享是進步的源泉。