FM2022牛津城純青訓5(2022/23賽季下)
shiro筆記
shiro簡述
- Apache Shiro 是java的一個安全框架
- Shiro 可以做:認證、授權、加密、會話管理、Web整合、快取等功能。
- 官網:http://shiro.apache.org/
功能介紹
- Authentication:身份認證/登入,驗證使用者是不是擁有相應的身份
- Authorization:授權,即許可權驗證,驗證某個已認證的使用者是否擁有某個許可權;
- Session Manager:會話管理,即使用者登入後就是一次會話,在沒有退出之前,它的所有資訊都在會話中;會話可以是普通 JavaSE 環境,也可以是 Web 環境的;
- Cryptography:加密,保護資料的安全性,如密碼加密儲存到資料庫,而不是明文儲存;
- Web Support:Web 支援,可以非常容易的整合到Web 環境;
- Caching:快取,比如使用者登入後,其使用者資訊、擁有的角色/許可權不必每次去查,這樣可以提高效率;
- Concurrency:Shiro 支援多執行緒應用的併發驗證,即如在一個執行緒中開啟另一個執行緒,能把許可權自動傳播過去;
- Testing: 提供 測試 支援
- Run As: 允許一個使用者假裝為另一個使用者(如果他們允許)的身份進行訪問;
- Remember Me:記住我,這個是非常常見的功能,即一次登入後,下次再來的話不用登入了
Shiro與Spring Security對比
共同點: 認證、授權、加密、會話、快取、remember Me功能...
不同點: Shiro配置和使用比較簡單,Spring Sccurity上手複雜.Shiro依賴性低,不需要任何框架和容器,可以獨立執行,而Spring Security依賴於Spring容器.
Shiro四大核心功能
Authentication
- 身份認證:
一般用於登入:登陸時,驗證使用者是否擁有相應身份。Authorization
- 訪問控制:
驗證已認證使用者是否擁有某些許可權,可以讓他進行許可權內的操作。Cryptography
- 密碼加密:
將密碼加密儲存到資料庫,而不是明文儲存,可以保護資料的安全性。Session Management
- 會話管理:
使用者登入後就是第一次會話,在會話結束(退出登入)前,他所有的資訊都在會話中。
Shiro三個核心元件
Subject-主體:
應用程式碼直接互動的物件是Subject,也就是說Shiro的對外API核心是Subject。
Subject的所有互動都會委託給SecurityManager(實際的執行者)。
SecurityManager-安全管理器:
SecurityManager是Shiro的核心,負責與Shiro的其他元件進行互動,相當於SpringMVC中DispatcherServlet的角色。
它管理著所有 Subject、且負責進行認證和授權、及會話、快取的管理,所有具體的互動都通過SecurityManager 進行控制。
SecurityManager是一個單例物件,一個應用中只需要一個SecurityManager.
Realm-域
Shiro從Realm獲取安全資料(如使用者、角色、許可權),
就是說SecurityManager要驗證使用者身份,那麼它需要從Realm獲取相應的使用者進行比較以確定使用者身份是否合法;
也需要從Realm得到使用者相應的角色/許可權進行驗證使用者是否能進行操作;
可以把Realm看成DataSource,即安全資料來源。
shiro中的認證
身份認證,就是判斷一個使用者是否為合法使用者的處理過程。最常見的簡單身份驗證方式是通過核對使用者輸入的使用者名稱和口令,看其是否與系統中儲存的該使用者的使用者名稱和口令一致,來判斷使用者身份是否正確。
shiro中認證的關鍵物件
- Subject:主體
訪問系統的使用者,主體可以是使用者、程式等。 - Principal:身份資訊
是主體進行身份認證的標識,標識必須具有唯一性,如使用者名稱、手機號、郵箱地址等。一個主體可以有多個身份,但是必須有一個主身份(Primary Principal)。 - credential:憑證資訊
是隻有主體自己知道的安全資訊,如密碼、證書等。
認證流程
認證的開發
- 建立Spring Boot專案
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.5.3</version>
</dependency>
- 引入shiro配置檔案
配置檔案:名稱隨意,以 .ini結尾,放在resources目錄下。
注意:在實際的專案開發中並不會使用這種方式,這種方法可以用來初學時練手!
[users]
king=123456
wang=123456
- 開發認證程式碼
public class ShiroDemo{
public static void main(String[] args){
//1.建立安全管理器物件
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2.給安全管理器設定realm
securityManager.setRealm(new InitRealm("classpath:shiro.ini"));
//3.SecurityUtils全域性安全工具類設定安全管理器
SecurityUtils.setSecurityManager(securityManager);
//4.關鍵物件subject主體
Subject subject = SecurityUtils.getSubject();
//5.建立令牌
UsernamePasswordToken token = new UsernamePasswordToken("king","123456");
try{
System.out.println("認證狀態"+subject.isAuthenticated());//fasle
//使用者認證
subject.login(token);
System.out.println("認證狀態"+subject.isAuthenticated());
}catch(UnknownAccountException e){
e.printStackTrace();
System.out.println("認證失敗,使用者名稱不存在");
}catch(IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("認證失敗,密碼錯誤");
}
}
}
- 常見的異常型別
- DisabledAccountException(帳號被禁用)
- LockedAccountException(帳號被鎖定)
- ExcessiveAttemptsException(登入失敗次數過多)
- ExpiredCredentialsException(憑證過期)等
自定義Realm
通過分析原始碼可得,
- 最終執行使用者名稱比較的的是 在SimpleAccountRealm類 的doGetAuthenticationInfo 方法完成使用者名稱校驗。
- 最終密碼校驗是在 AuthenticatingRealm類 的 assertCredentialsMatch方法 中。
shiro提供的Realm
根據認證原始碼認證使用的是SimpleAccountRealm
接下里,開始自定義realm!
public class CustomerRealm extends AuthorizingRealm{
//授權
@Override
protected
}