簡介
Apache Shiro是Java的一個安全框架。目前,使用Apache Shiro的人越來越多,因爲它相當簡單,對比Spring Security,可能沒有Spring Security做的功能強大,但是在實際工作時可能並不需要那麼複雜的東西,所以使用小而簡單的Shiro就足夠了。對於它倆到底哪個好,這個不必糾結,能更簡單的解決項目問題就好了。
Shiro可以非常容易的開發出足夠好的應用,其不僅可以用在JavaSE環境,也可以用在JavaEE環境。Shiro可以幫助我們完成:認證、授權、加密、會話管理、與Web集成、緩存等,在此我僅僅介紹我們公司使用的認證、授權、加密功能,對於其他功能,小夥伴可以發揮一下自學能力呦
在此讓我們來了解一些shiro的一些基本的術語
Authentication:
身份認證/登錄,驗證用戶是不是擁有相應的身份;
Authorization:
授權,即權限驗證,驗證某個已認證的用戶是否擁有某個權限;即判斷用戶是否能做事情,常見的如:驗證某個用戶是否擁有某個角色。或者細粒度的驗證某個用戶對某個資源是否具有某個權限;
Cryptography:
加密,保護數據的安全性,如密碼加密存儲到數據庫,而不是明文存儲;
Subject:
主體,代表了當前“用戶”,這個用戶不一定是一個具體的人,與當前應用交互的任何東西都是Subject,如網絡爬蟲,機器人等;即一個抽象概念;所有Subject都綁定到SecurityManager,與Subject的所有交互都會委託給SecurityManager;可以把Subject認爲是一個門面;SecurityManager纔是實際的執行者;
SecurityManager:
相當於SpringMVC中的DispatcherServlet或者Struts2中的FilterDispatcher;是Shiro的心臟;所有具體的交互都通過SecurityManager進行控制;它管理着所有Subject、且負責進行認證和授權、及會話、緩存的管理
Realm:
域,Shiro從從Realm獲取安全數據(如用戶、角色、權限),就是說SecurityManager要驗證用戶身份,那麼它需要從Realm獲取相應的用戶進行比較以確定用戶身份是否合法;也需要從Realm得到用戶相應的角色/權限進行驗證用戶是否能進行操作;可以把Realm看成DataSource,即安全數據源。
-
token
token相當於一個令牌,是將用戶的一些信息(如賬號、密碼、等)經過散列然後生成一個無意義的字符串保存在數據庫或者redis,散列不可逆,用戶登錄時只能通過重新散列然後得到串和數據庫中的串做比較,看是否相同判定賬號密碼是否正確
shiro運行流程
- 首先,我們從外部來看Shiro吧,即從應用程序角度的來觀察如何使用Shiro完成工作
- 應用代碼通過Subject來進行認證和授權,而Subject又委託給SecurityManager;
- 我們需要給Shiro的SecurityManager注入Realm,從而讓SecurityManager能得到合法的用戶及其權限 進行判斷。
- 對於realm的詳解
相信看完上面的工作流程圖大家一定會產生一個疑問-->爲什麼要realm?請看下文分析。。。。
shiro作爲一個安全授權框架,對於用戶安全登錄上,怎樣的用戶是安全的?怎怎樣的用戶是可以進入的?樣的用戶該擁有什麼樣的權限?相信這些只有開發者才知道,realm正是shiro留給開發者用於自定義用戶登錄驗證和授權認證的一個類,我們可以通過實現Realm接口創建一個自定義的realm類,用於自定義用戶登錄驗證方式(AuthenticationInfo來完成)和授權驗證(AuthorizationInfo來完成)
登錄驗證
相信大家通過上面的講解對shiro已經有了一些基本的瞭解,那麼接下來我將通過我們公司封裝的shiro框架爲例,向大家揭祕登錄和授權功能
- 編寫TokenFilter來進行登錄驗證
- 在配置文件裏面配置需要進行驗證的一些mappering
- 讓我們來看一下filter裏面主要的一個類
- 首先他調用了一個gettoken方法,返回了一個Token,讓我們看一下gettoken方法
通過查看代碼,我們知道這個token來自於請求域,來自於用戶填寫的信息
- 再回到filter中我們會發現這麼一句代碼
boolean loginSuccess = this.login(new Token(token));
將獲得的token傳入到一個login方法中,接下來讓我們順着這裏往下走,來到了另一個login,裏面有這麼一句-->subject.login(token);
- 進入subject.login(token),順着一直走我們會發現這麼一個類
在這個方法裏面我們可以發現這麼一句-->info = authenticate(token);,我們可以發現這就是在間接地調用relam類裏面的我們自動以的驗證方法
- 讓我們進入relam的doGetAuthenticationInfo
我們會發現他是通過用戶數據爲key在redis中嘗試獲取有沒有對應的value,來證明是否這個用戶曾經註冊過,或者賬號密碼和一些信息是否正確
授權
關於授權的一些概念
主體
主體,即訪問應用的用戶,在Shiro中使用Subject代表該用戶。用戶只有授權後才允許訪問相應的資源。
資源
在應用中用戶可以訪問的任何東西,比如訪問JSP頁面、查看/編輯某些數據、訪問某個業務方法、打印文本等等都是資源。用戶只要授權後才能訪問。
權限
安全策略中的原子授權單位,通過權限我們可以表示在應用中用戶有沒有操作某個資源的權力。即權限表示在應用中用戶能不能訪問某個資源,如:
訪問用戶列表頁面
查看/新增/修改/刪除用戶數據(即很多時候都是CRUD(增查改刪)式權限控制)
打印文檔等等。。。
如上可以看出,權限代表了用戶有沒有操作某個資源的權利,即反映在某個資源上的操作允不允許,不反映誰去執行這個操作。所以後續還需要把權限賦予給用戶,即定義哪個用戶允許在某個資源上做什麼操作(權限),Shiro不會去做這件事情,而是由實現人員提供。
Shiro支持粗粒度權限(如用戶模塊的所有權限)和細粒度權限(操作某個用戶的權限,即實例級別的),後續部分介紹。
角色
角色代表了操作集合,可以理解爲權限的集合,一般情況下我們會賦予用戶角色而不是權限,即這樣用戶可以擁有一組權限,賦予權限時比較方便。典型的如:項目經理、技術總監、CTO、開發工程師等都是角色,不同的角色擁有一組不同的權限。
隱式角色:
即直接通過角色來驗證用戶有沒有操作權限,如在應用中CTO、技術總監、開發工程師可以使用打印機,假設某天不允許開發工程師使用打印機,此時需要從應用中刪除相應代碼;再如在應用中CTO、技術總監可以查看用戶、查看權限;突然有一天不允許技術總監查看用戶、查看權限了,需要在相關代碼中把技術總監角色從判斷邏輯中刪除掉;即粒度是以角色爲單位進行訪問控制的,粒度較粗;如果進行修改可能造成多處代碼修改。
顯示角色:
在程序中通過權限控制誰能訪問某個資源,角色聚合一組權限集合;這樣假設哪個角色不能訪問某個資源,只需要從角色代表的權限集合中移除即可;無須修改多處代碼;即粒度是以資源/實例爲單位的;粒度較細。、
授權方式
Shiro支持三種方式的授權:
1.編程式:通過寫if/else授權代碼塊完成:
Java代碼
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
//有權限
} else {
//無權限
}
註解式:通過在執行的Java方法上放置相應的註解完成:
Java代碼 收藏代碼
@RequiresRoles("admin")
public void hello() {
//有權限
}
沒有權限將拋出相應的異常;
JSP/GSP標籤:在JSP/GSP頁面通過相應的標籤完成:
Java代碼
<shiro:hasRole name="admin">
<!— 有權限 —>
</shiro:hasRole>
我們 公司如何用shiro做權限
- 我們公司採用註解的方法來進行權限控制
這是我從公司一個勘察項目中截下的一段代碼可以看到-->@RequiresRoles。。。。
它的意思就是後面的角色裏只要用戶有其中一個角色就可以使用這個方法
- 讓我們來看realm裏面的AuthorizationInfo方法(這個方法用於做權限的認定)
我們可以發現它先拿到一個userid,然後通過userid爲key在redis中尋找value,然後將權限信息放入info返回,對此大家一定很好奇他在redis中拿了什麼
- 讓我們來看看它在redis中拿了什麼
我們查看redis發現它拿了一個數字
- 這個數字就代表着他的角色,而每個角色有每個角色的權限
以上,就是今天的全部內容。
增鑫
蘆葦科技Java開發工程師
蘆葦科技-廣州專業軟件外包服務公司
提供微信小程序、APP應用研發、UI設計等專業服務,專注於互聯網產品諮詢、品牌設計、技術研發等領域、
訪問 www.talkmoney.cn 瞭解更多
萬能說明書 | 早起日記Lite | 凹凸壁紙 | 言財