在最近的一個項目當中,咱們基於Shiro實現咱們系統的認證和受權。藉此機會,寫幾篇博客,總結一下在本次實踐當中遇到的問題,和較全面地學習一下Shiro的知識點,java
權限管理實現對用戶訪問系統的控制,按照安全規則或者安全策略控制用戶訪問並且只能訪問受權訪問的資源。web
權限管理主要分爲兩個部分,一是身份認證(authentication),二是受權(authorization)。spring
目前主流的解決方案spring security+JWT或者Shiro+JWT方案。固然也有相關團隊(公司)是本身編寫過濾器進行訪問控制。但這並不值得推薦,除非你設計的權限管理方案能經得起生產環境的考驗。數據庫
若是你們須要瞭解關於spring security的相關內容,能夠閱讀我spring security的相關文章。apache
權限管理模型的話,主要有這麼幾種:windows
自主訪問控制(DAC: Discretionary Access Control)。一個典型的例子就是windows操做系統的權限管理。DAC 最大的缺陷就是對權限控制比較分散,不便於管理,好比說簡單地對一組文件設置統一的權限並授予指定的一組用戶。安全
強制訪問控制模型(MAC: Mandatory Access Control)。MAC爲了彌補DAC而生,MAC給用戶和資源分別數字化標記其權限等級。當用戶訪問某一資源時,只有它的權限等級高於或等於資源的權限等級時,才能訪問,不然拒絕訪問。好比存在某一資源404.MP4,資源等級爲1024.存在用戶Ferrayman,其權限等級爲256,存在用戶boss,其權限等級爲2048.那麼,boss就能正常訪問資源404.MP4,而Ferrayman則無權訪問。網絡
基於角色的訪問控制模型(RBAC: Role-based Access Control),即給用戶分配角色,角色下對應必定的資源,用戶對其角色下的資源具備訪問權限。RBAC細分爲RBAC0、RBAC一、RBAC二、RBAC3幾個版本。session
咱們主要採用的也是RBAC模型。app
Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.
Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、受權、密碼和會話管理。使用Shiro的易於理解的API,您能夠快速、輕鬆地得到任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序。
Shiro三大組件:Subject, SecurityManager 和 Realms.
即「當前主體」。在Shiro中,Subject這一律念並不只僅指人,也能夠是第三方進程、後臺賬戶(Daemon Account)或其餘相似事物。它僅僅意味着「當前跟軟件交互的東西」。Subject表明了當前用戶的安全操做,SecurityManager則管理全部用戶的安全操做。
它主要由身份信息Principal和憑證Principals組成。Principal能夠理解爲主體在系統中的帳號,且是具備惟一性的。Principals能夠理解爲主體在當前系統帳戶所對應的密碼、證書。
它是Shiro框架的核心,典型的Facade模式,Shiro經過SecurityManager來管理內部組件實例,並經過它來提供安全管理的各類服務。
Realm充當了Shiro與應用安全數據間的「橋樑」或者「鏈接器」。也就是說,當對用戶執行認證(登陸)和受權(訪問控制)驗證時,Shiro會從應用配置的Realm中查找用戶及其權限信息。
從這個意義上講,Realm實質上是一個安全相關的DAO:它封裝了數據源的鏈接細節,並在須要時將相關數據提供給Shiro。當配置Shiro時,你必須至少指定一個Realm,用於認證和(或)受權。配置多個Realm是能夠的,可是至少須要一個。
Shiro內置了能夠鏈接大量安全數據源(又名目錄)的Realm,如LDAP、關係數據庫(JDBC)、相似INI的文本配置資源以及屬性文件等。若是缺省的Realm不能知足需求,你還能夠插入表明自定義數據源的本身的Realm實現。
簡單、靈活。
使用起來相對於spring security簡單。不只支持Web應用也支持非Web應用,無縫集成。
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.5.3</version> </dependency> <!--方便測試--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
shiro的配置文件是以「.ini」結尾的文件。之因此使用.ini格式,是由於該文件類型支持比較複雜的數據格式。主要用來存儲shiro的一些權限數據。這個主要是拿來學習shiro用的,平時項目中,權限數據存儲於數據庫中。
配置主體的身份信息和憑證
[users] xiangbei=123 xiangname=123
package pers.lbf.shirodemo.core; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.realm.text.IniRealm; import org.apache.shiro.subject.Subject; /**認證器 * @author 賴柄灃 bingfengdev@aliyun.com * @version 1.0 * @date 2020/9/21 0:50 */ public class Authenticator { private DefaultSecurityManager securityManager; public Authenticator(){ //1. 建立安全管理器 this.securityManager = new DefaultSecurityManager(); //2. 給安全管理器設置問題域 //由於權限信息從ini文件中讀取,因此是IniRealm this.securityManager.setRealm(new IniRealm("classpath:shiro.ini")); //3. 注入安全管理器,並使用SecurityUtils全局安全工具類完成認證 SecurityUtils.setSecurityManager(securityManager); } /**認證 * @author 賴柄灃 bingfengdev@aliyun.com * @date 2020-09-23 16:22:11 * @param username 用戶名 * @param password 密碼 * @return void * @version 1.0 */ public void authenticate(String username,String password){ //4. 獲取當前主題 Subject subject = SecurityUtils.getSubject(); //5.根據登陸對象身份憑證信息建立登陸令牌 UsernamePasswordToken token = new UsernamePasswordToken(username,password); //6.認證 //若是認證經過,則不拋出異常,不然拋出AuthenticationExceptixon異常子類 //正式項目建議直接拋出,統一異常處理 try { subject.login(token); }catch (IncorrectCredentialsException e) { e.printStackTrace(); }catch (ConcurrentAccessException e){ e.printStackTrace(); }catch (UnknownAccountException e){ e.printStackTrace(); }catch (ExcessiveAttemptsException e){ e.printStackTrace(); }catch (ExpiredCredentialsException e){ e.printStackTrace(); }catch (LockedAccountException e){ e.printStackTrace(); } } }
package shirodemo; import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; import org.junit.Before; import org.junit.Test; import pers.lbf.shirodemo.core.Authenticator; /**測試認證 * @author 賴柄灃 bingfengdev@aliyun.com * @version 1.0 * @date 2020/9/21 0:49 */ public class TestAuthenticator { private Authenticator authenticator=null; @Before public void init() { authenticator = new Authenticator(); } @Test public void testAuth(){ authenticator.authenticate("xiangbei","123"); } }
今天,咱們主要經過一個簡單的demo,去開始學習shiro的相關知識。但這些知識還不足以讓咱們應用到咱們的產品中去,接下來的shiro系列修仙功法(文章),做者將跟着你們一塊兒去學習shiro的應用。