shiro基礎學習(二)—shiro認證


一、shiro簡介

     shiro是apache旗下一個開源框架,它將軟件系統的安全認證相關的功能抽取出來,實現用戶身份認證、權限授權、加密、會話管理等功能,組成了一個通用的安全認證框架。

以下是你可以用 Apache Shiro所做的事情:

(1)驗證用戶。

(2)對用戶執行訪問控制,如: 判斷用戶是否擁有角色admin,判斷用戶是否擁有訪問的權限。

(3)在任何環境下使用Session API。例如CS程序。

(4)可以使用多個用戶數據源。例如一個是oracle用戶庫,另外一個是mysql用戶庫。

(5)單點登錄(SSO)功能。

(6)"Remember Me"服務,類似購物車的功能,shiro官方建議開啟。

 

二、shiro架構

     image

 

(1)Subject

     image

     Subject 是與程序進行交互的對象,可以是人也可以是服務或者其他,通常就理解為用戶。

     所有Subject 實例都必須綁定到一個SecurityManager上。我們與一個 Subject 交互,運行時shiro會自動轉化為與 SecurityManager交互的特定 subject的交互。

     Subject在shiro中是一個接口,接口中定義了很多認證授權相關的方法,外部程序通過subject進行認證授,而subject是通過SecurityManager安全管理器進行認證授權。

 

(2)SecurityManager

     SecurityManager即安全管理器,對全部的subject進行安全管理,它是shiro的核心,負責對所有的subject進行安全管理。通過SecurityManager可以完成subject的認證、授權等,實質上SecurityManager是通過Authenticator進行認證,通過Authorizer進行授權,通過SessionManager進行會話管理等。

     SecurityManager是一個接口,繼承了Authenticator, Authorizer, SessionManager這三個接口。

 

(3)Authenticator

     Authenticator即認證器,對用戶身份進行認證,Authenticator是一個接口,shiro提供ModularRealmAuthenticator實現類,通過ModularRealmAuthenticator基本上可以滿足大多數需求,也可以自定義認證器。

 

(4)Authorizer

    Authorizer即授權器,用戶通過認證器認證通過,在訪問功能時需要通過授權器判斷用戶是否有此功能的操作權限。

 

(5)Realm

     Realm即領域,相當於datasource數據源,securityManager進行安全認證需要通過Realm獲取用戶權限數據,比如:如果用戶身份數據在數據庫那么realm就需要從數據庫獲取用戶身份信息。

注意:不要把realm理解成只是從數據源取數據,在realm中還有認證授權校驗的相關的代碼。

 

(6)sessionManager

     sessionManager即會話管理,shiro框架定義了一套會話管理,它不依賴web容器的session,所以shiro可以使用在非web應用上,也可以將分布式應用的會話集中在一點管理,此特性可使它實現單點登錄。

 

(7)SessionDAO

     SessionDAO會話dao,是對session會話操作的一套接口,比如要將session存儲到數據庫,可以通過jdbc將會話存儲到數據庫。

 

(8)CacheManager

     CacheManager即緩存管理,將用戶權限數據存儲在緩存,這樣可以提高性能。

 

(9)Cryptography

     Cryptography即密碼管理,shiro提供了一套加密/解密的組件,方便開發。比如提供常用的散列、加/解密等功能。

 

三、基本程序

1.認證流程

       image

 

2.入門程序

(1)工程架構

image

 

(2)shiro-first.ini

     通過shiro-first.ini配置文件初始化SecurityManager環境。

    image

 

(3)代碼實現

public class AuthenticationTest{

	// 用戶登錄和退出
	@Test
	public void testLogin(){

		// 創建SecurityManager工廠,通過init配置文件構造
		IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro-first.ini");

		// 創建SecurityManager
		SecurityManager securityManager = factory.createInstance();

		// 將SecurityManager設置到當前運行環境
		SecurityUtils.setSecurityManager(securityManager);

		// 從SecurityUtils里創建Subject
		Subject subject = SecurityUtils.getSubject();

		// 認證提交前准備token
		UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123");

		try{
			// 執行認證提交
			subject.login(token);
		}catch(Exception e){
			e.printStackTrace();
		}

		// 是否認證通過
		boolean isAuthenticated = subject.isAuthenticated();
		System.out.println("是否認證通過: " + isAuthenticated);

		// 退出操作
		subject.logout();

		isAuthenticated = subject.isAuthenticated();
		System.out.println("是否認證通過: " + isAuthenticated);
	}
}

結果:

      是否認證通過: true
      是否認證通過: false

 

(4)認證流程

1、通過ini配置文件創建securityManager

2、調用subject.login方法主體提交認證,提交的token

3、securityManager進行認證,securityManager最終由ModularRealmAuthenticator進行認證。

4、ModularRealmAuthenticator調用IniRealm(給realm傳入token) 去ini配置文件中查詢用戶信息。

5、IniRealm根據輸入的token(UsernamePasswordToken)從shiro-first.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)。

 

三、自定義Realm

1.自定義Realm代碼實現

/*
 * 自定義Realm
 */
public class CustomRealm extends AuthorizingRealm{

	
	//設置Realm名稱
	@Override
	public void setName(String name){
		super.setName("customRealm");
	}

	//用於認證
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException{
		
		//1.從token取出用戶身份信息
		String userCode = (String)token.getPrincipal();
		
		//2.根據用戶userCode查詢數據庫
		//模擬從數據庫查詢到的密碼
		String password = "123";
		
		//查詢不到返回null
		
		//查詢到返回認證信息
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userCode,password,this.getName());
		
		return authenticationInfo;
	}

	//用於授權
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){
		
		return null;
	}

}

 

2.配置Realm

image

 

3.測試代碼

	// 用戶登錄和退出
	@Test
	public void testCustomRealm(){
		
		// 創建SecurityManager工廠,通過init配置文件構造
		IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
		
		// 創建SecurityManager
		SecurityManager securityManager = factory.createInstance();
		
		// 將SecurityManager設置到當前運行環境
		SecurityUtils.setSecurityManager(securityManager);
		
		// 從SecurityUtils里創建Subject
		Subject subject = SecurityUtils.getSubject();
		
		// 認證提交前准備token
		UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123");
		
		try{
			// 執行認證提交
			subject.login(token);
		}catch(Exception e){
			e.printStackTrace();
		}
		
		// 是否認證通過
		boolean isAuthenticated = subject.isAuthenticated();
		
		System.out.println("是否認證通過: " + isAuthenticated);
		
		// 退出操作
		subject.logout();
		
		isAuthenticated = subject.isAuthenticated();
		System.out.println("是否認證通過: " + isAuthenticated);
	}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM