Shiro初识
為什么80%的碼農都做不了架構師?>>> ??
簡介
Shiro(希羅)的前身叫JSecurity項目,始于2003年,2008年加入Apache軟件基金會并成為Apache頂級項目。
- 官網:http://shiro.apache.org/
- github:https://github.com/apache/shiro
Shiro是一個強大而靈活的開源Java安全框架,提供了認證、授權、密碼加密、會話管理等功能。
Authentication:身份認證/登錄,驗證用戶是不是擁有相應的身份;
Authorization:授權,即權限驗證,驗證某個已認證的用戶是否擁有某個權限;即判斷用戶是否能做事情,常見的如:驗證某個用戶是否擁有某個角色。或者細粒度的驗證某個用戶對某個資源是否具有某個權限;
Session Manager:會話管理,即用戶登錄后就是一次會話,在沒有退出之前,它的所有信息都在會話中;會話可以是普通JavaSE環境的,也可以是如Web環境的;
Cryptography:加密,保護數據的安全性,如密碼加密存儲到數據庫,而不是明文存儲;
Web Support:Web支持,可以非常容易的集成到Web環境;
Caching:緩存,比如用戶登錄后,其用戶信息、擁有的角色/權限不必每次去查,這樣可以提高效率;
Concurrency:shiro支持多線程應用的并發驗證,即如在一個線程中開啟另一個線程,能把權限自動傳播過去;
Testing:提供測試支持;
Run As:允許一個用戶假裝為另一個用戶(如果他們允許)的身份進行訪問;
Remember Me:記住我,這個是非常常見的功能,即一次登錄后,下次再來的話不用登錄了。
記住一點,Shiro不會去維護用戶、維護權限;這些需要我們自己去設計/提供;然后通過相應的接口注入給Shiro即可。
核心概念
Subject: 一個安全術語,意指“當前用戶”,這里的用戶可以指人、第三方進程等其他事物。一旦獲得Subject,你就可以立即獲得你希望用Shiro為當前用戶做的90%的事情,如登錄、登出、訪問會話、執行授權檢查等。這里的關鍵點是Shiro的API非常直觀,因為它反映了開發者以‘每個用戶’思考安全控制的自然趨勢。同時,在代碼的任何地方都能很輕松地訪問Subject,允許在任何需要的地方進行安全操作。所有Subject都綁定到SecurityManager,與Subject的所有交互都會委托給SecurityManager;可以把Subject認為是一個門面;SecurityManager才是實際的執行者。
Subject subject = SecurityUtils.getSubject();subject.login();SecurityManager:安全管理器;shiro框架的核心,管理所有用戶更的安全操作,引用了多個內部嵌套安全組件(如Realm、Session的管理器等);
@Bean public SecurityManager securityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 設置realmsecurityManager.setRealm(myShiroRealm());// 記住我securityManager.setRememberMeManager(rememberMeManager());// 自定義緩存實現 使用redissecurityManager.setCacheManager(redisCacheManager());// 自定義session管理 使用redissecurityManager.setSessionManager(sessionManager());return securityManager; }Realm:域,Shiro從Realm獲取安全數據(如用戶、角色、權限),就是說SecurityManager要驗證用戶身份,那么它需要從Realm獲取相應的用戶進行比較以確定用戶身份是否合法;也需要從Realm得到用戶相應的角色/權限進行驗證用戶是否能進行操作;可以把Realm看成DataSource,即安全數據源。Realm有兩個關鍵方法:
public class MyRealm extends AuthorizingRealm {@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {// 認證return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)throws AuthenticationException {// 授權return null;} }Filter鏈:Shiro通過其創新的URL過濾器鏈功能支持安全特定的過濾規則,它允許你為任何匹配的URL模式指定非正式的過濾器鏈。
使用
????常規使用:https://github.com/asdf08442a/demo2-0
????前后端分離:https://blog.csdn.net/u013615903/article/details/78781166
特點
- 易于理解的 Java Security API;
- 簡單的身份認證(登錄),支持多種數據源(LDAP,JDBC,Kerberos,ActiveDirectory 等);
- 對角色的簡單的簽權(訪問控制),支持細粒度的簽權;
- 支持一級緩存,以提升應用程序的性能;
- 內置的基于 POJO 企業會話管理,適用于 Web 以及非 Web 的環境;
- 異構客戶端會話訪問;
- 非常簡單的加密 API;
- 不跟任何的框架或者容器捆綁,可以獨立運行。
源碼解讀
- Shiro之入口:EnvironmentLoaderListener
- Shiro之Filter(上):ShiroFilter
- Shiro之Realm
- Shiro之SecurityManager
流程
認證過程
1、通過ini配置文件創建securityManager
2、調用subject.login方法主體提交認證,提交的token
3、securityManager進行認證,securityManager最終由ModularRealmAuthenticator進行認證。
4、ModularRealmAuthenticator調用IniRealm(給realm傳入token) 去ini配置文件中查詢用戶信息
5、IniRealm根據輸入的token(UsernamePasswordToken)從 shiro.ini查詢用戶信息,根據賬號查詢用戶信息(賬號和密碼)
?????????如果查詢到用戶信息,就給ModularRealmAuthenticator返回用戶信息(賬號和密碼)
?????????如果查詢不到,就給ModularRealmAuthenticator返回null
6、ModularRealmAuthenticator接收IniRealm返回Authentication認證信息
?????????如果返回的認證信息是null,ModularRealmAuthenticator拋出異常(org.apache.shiro.authc.UnknownAccountException)
?????????如果返回的認證信息不是null(說明inirealm找到了用戶),對IniRealm返回用戶密碼 (在ini文件中存在)
?????????和 token中的密碼 進行對比,如果不一致拋出異常(org.apache.shiro.authc.IncorrectCredentialsException)
授權流程
1、對subject進行授權,調用方法isPermitted("permission串")
2、SecurityManager執行授權,通過ModularRealmAuthorizer執行授權
3、ModularRealmAuthorizer執行realm(自定義的Realm)從數據庫查詢權限數據,調用realm的授權方法:doGetAuthorizationInfo
4、realm從數據庫查詢權限數據,返回ModularRealmAuthorizer
5、ModularRealmAuthorizer調用PermissionResolver進行權限串比對
6、如果比對后,isPermitted中"permission串"在realm查詢到權限數據中,說明用戶訪問permission串有權限,否則 沒有權限,拋出異常。
Filters
| 配置? 縮寫? | 對應的過濾器 | 功能 |
| anon | AnonymousFilter | 指定url可以匿名訪問 |
| authc | FormAuthenticationFilter | 指定url需要form表單登錄,默認會從請求中獲取username、password,rememberMe等參數并嘗試登錄,如果登錄不了就會跳轉到loginUrl配置的路徑。我們也可以用這個過濾器做默認的登錄邏輯,但是一般都是我們自己在控制器寫登錄邏輯的,自己寫的話出錯返回的信息都可以定制嘛. |
| authcBasic | BasicHttpAuthenticationFilter | 指定url需要basic登錄 |
| logout | LogoutFilter | 登出過濾器,配置指定url就可以實現退出功能,非常方便 |
| noSessionCreation | NoSessionCreationFilter | 禁止創建會話 |
| perms | PermissionsAuthorizationFilter | 需要指定權限才能訪問 |
| port | PortFilter | 需要指定端口才能訪問 |
| rest | HttpMethodPermissionFilter | 將http請求方法轉化成相應的動詞來構造一個權限字符串,這個感覺意義不大,有興趣自己看源碼的注釋 |
| roles | RolesAuthorizationFilter | 需要指定角色才能訪問 |
| ssl | SslFilter | 需要https請求才能訪問 |
| user | UserFilter | 需要已登錄或“記住我”的用戶才能訪問 |
| ? | ? | ? |
以上是shiro的一些Filter,如我們在filterChainDefinitions里配置了/admin=authc,roles[admin],那么/admin這個請求會由org.apache.shiro.web.filter.authc.FormAuthenticationFilter和org.apache.shiro.web.filter.authz.RolesAuthorizationFilter這兩個filter來處理,其中authc,roles只是filter的別名。
轉載于:https://my.oschina.net/jzgycq/blog/2056287
總結
- 上一篇: PHP无限极分类原理
- 下一篇: ArrayList 除重