更新時間:2022-02-08 10:51:04 來源:動力節點 瀏覽910次
Shiro 將 Permission 定義為定義顯式行為或動作的語句。它是應用程序中原始功能的聲明,僅此而已。權限是安全策略中最低級別的結構,它們僅明確定義應用程序可以做什么。
他們根本沒有描述“誰”能夠執行這些操作。
一些權限示例:
打開一個文件
查看“/用戶/列表”網頁
打印文件
刪除“jsmith”用戶
定義“誰”(用戶)被允許做“什么”(權限)是以某種方式為用戶分配權限的練習。這始終由應用程序的數據模型完成,并且在應用程序之間可能會有很大差異。
例如,權限可以分組在一個角色中,并且該角色可以與一個或多個用戶對象相關聯。或者某些應用程序可以有一個用戶組,并且可以為一個組分配一個角色,通過傳遞關聯意味著該組中的所有用戶都被隱式授予角色中的權限。
授予用戶權限的方式有很多變化 - 應用程序根據應用程序要求確定如何對其進行建模。
上面的權限示例,“打開文件”,“查看‘用戶/列表’網頁”等都是有效的權限聲明。但是,在計算上解釋這些自然語言字符串并確定用戶是否是非常困難的是否允許執行該行為。
因此,為了啟用易于處理但仍然可讀的權限語句,Shiro 提供了強大而直觀的權限語法,我們稱之為 WildcardPermission。
假設您想保護對公司打印機的訪問,以便某些人可以打印到特定的打印機,而其他人可以查詢當前隊列中的作業。
一個非常簡單的方法是授予用戶“queryPrinter”權限。然后您可以通過調用來檢查用戶是否具有 queryPrinter 權限:
subject.isPermitted("queryPrinter")
這(大部分)相當于
subject.isPermitted( new WildcardPermission("queryPrinter") )
但稍后會詳細介紹。
簡單權限字符串可能適用于簡單的應用程序,但它要求您具有“printPrinter”、“queryPrinter”、“managePrinter”等權限。您還可以使用通配符授予用戶“*”權限(授予此權限構造它的名字),這意味著他們擁有整個應用程序的所有權限。
但是使用這種方法沒有辦法只說用戶擁有“所有打印機權限”。因此,通配符權限支持多級權限。
通配符權限支持多個級別或部分的概念。例如,您可以通過授予用戶權限來重構前面的簡單示例
printer:query
此示例中的冒號是一個特殊字符,用于分隔權限字符串中的下一部分。
在此示例中,第一部分是正在操作的域 ( printer),第二部分是query正在執行的操作 ( )。上面的其他示例將更改為:
printer:print
printer:manage
可以使用的部件數量沒有限制,因此在您的應用程序中使用它的方式取決于您的想象力。
每個部分可以包含多個值。因此,您可以簡單地授予用戶一個“printer:print”和“printer:query”權限,而不是授予用戶“printer:print”和“printer:query”權限:
printer:print,query
這使他們能夠print和query打印機。由于他們被授予這兩個操作,您可以通過調用來檢查用戶是否有能力查詢打印機:
subject.isPermitted("printer:query")
這將返回true
如果您想授予用戶特定部分中的所有值怎么辦?這樣做比手動列出每個值更方便。同樣,基于通配符,我們可以做到這一點。如果printer域有 3 個可能的操作(query、print和manage),則:
printer:query,print,manage
簡單地變成這樣:
printer:*
然后,任何對“printer:XXX”的權限檢查都會返回true。以這種方式使用通配符比明確列出操作具有更好的擴展性,因為如果您稍后向應用程序添加新操作,則無需更新在該部分中使用通配符的權限。
最后,還可以在通配符權限字符串的任何部分使用通配符標記。例如,如果您想授予用戶跨所有域(不僅僅是打印機)的“查看”操作,您可以授予此權限:
*:view
然后對“foo:view”的任何權限檢查都會返回true
雖然權限分配使用通配符構造相當多(“打印機:打印:*”=打印到任何打印機)以方便和可擴展性,但運行時的權限檢查應始終基于可能的最具體的權限字符串。
例如,如果用戶有一個 UI 并且他們想將文檔打印到lp7200打印機,您應該通過執行以下代碼來檢查用戶是否被允許這樣做:
if ( SecurityUtils.getSubject().isPermitted("printer:print:lp7200") ) {
//print the document to the lp7200 printer }
}
該檢查非常具體,并明確反映了用戶當時試圖做什么。
但是,對于運行時檢查,以下內容不太理想:
if ( SecurityUtils.getSubject().isPermitted("printer:print") ) {
//print the document }
}
為什么?因為第二個示例說“您必須能夠打印到任何打印機才能執行以下代碼塊”。但請記住,“printer:print”等價于“printer:print:*”!
因此,這是不正確的檢查。如果當前用戶沒有能力打印到任何打印機,但他們確實有能力打印lp7200到打印機,該怎么辦epsoncolor。那么上面的第二個示例將永遠不允許他們打印到lp7200打印機,即使他們已被授予該能力!
因此,經驗法則是在執行權限檢查時盡可能使用最具體的權限字符串。當然,如果您真的只想在允許用戶打印到任何打印機(懷疑,但可能)時執行代碼塊,那么上面的第二個塊可能是應用程序中其他地方的有效檢查。您的應用程序將確定哪些檢查有意義,但一般來說,越具體越好。如果大家想了解更相關知識,不妨來關注一下動力節點的Java視頻,里面的課程細致全面,從入門到精通,適合沒有基礎的小白學習,希望對大家能夠有所幫助。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習