1. 程式人生 > >第六章 Realm及相關物件(四) PrincipalCollection

第六章 Realm及相關物件(四) PrincipalCollection


之前使用過的(來點印象)

login("classpath:shiro-authenticator-all-success.ini");
Subject subject = SecurityUtils.getSubject();
//得到一個身份集合,其包含了Realm驗證成功的身份資訊
PrincipalCollection principalCollection = subject.getPrincipals();
Assert.assertEquals(2, principalCollection.asList().size());
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
	String username = (String) principals.getPrimaryPrincipal();
	SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
	authorizationInfo.setRoles(userService.findRoles(username));
	authorizationInfo.setStringPermissions(userService.findPermissions(username));
	return authorizationInfo;
}

PrincipalCollection是一個身份集合,因為我們可以在Shiro中同時配置多個Realm,所以呢身份資訊可能就有多個;因此其提供了PrincipalCollection用於聚合這些身份資訊:

public interface PrincipalCollection extends Iterable, Serializable {
	Object getPrimaryPrincipal(); //得到主要的身份
	<T> T oneByType(Class<T> type); //根據身份型別獲取第一個
	<T> Collection<T> byType(Class<T> type); //根據身份型別獲取一組
	List asList(); //轉換為List
	Set asSet(); //轉換為Set
	Collection fromRealm(String realmName); //根據Realm名字獲取
	Set<String> getRealmNames(); //獲取所有身份驗證通過的Realm名字
	boolean isEmpty(); //判斷是否為空
}

因為PrincipalCollection聚合了多個,此處最需要注意的是getPrimaryPrincipal,如果只有一個Principal 那麼直接返回即可,如果有多個Principal,則返回第一個(因為內部使用Map儲存,所以可以認為是返回任意一個);oneByType / byType根據憑據的型別返回相應的Principal;fromRealm 根據Realm 名字(每個Principal 都與一個Realm 關聯)獲取相應的Principal。

MutablePrincipalCollection是一個可變的PrincipalCollection介面,即提供瞭如下可變方法:

public interface MutablePrincipalCollection extends PrincipalCollection {
	void add(Object principal, String realmName); //新增Realm-Principal的關聯
	void addAll(Collection principals, String realmName); //新增一組Realm-Principal的關聯
	void addAll(PrincipalCollection principals);//新增PrincipalCollection
	void clear();//清空
}

目前Shiro只提供了一個實現SimplePrincipalCollection,還記得之前的AuthenticationStrategy實現嘛,用於在多Realm 時判斷是否滿足條件的,在大多數實現中(繼承了
AbstractAuthenticationStrategy)afterAttempt 方法會進行AuthenticationInfo(實現了MergableAuthenticationInfo)的merge,比如SimpleAuthenticationInfo 會合並多個Principal為一個PrincipalCollection。

示例:

1. 準備三個Realm

public class MyRealm1 implements Realm{
	public AuthenticationInfo getAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
				"zhang",	//身份 字串型別
				"123",		//憑據
				getName()	//Realm Name
		);
		return simpleAuthenticationInfo;
	}
	public String getName() {
		return "a";	//realm name為"a"
	}
	public boolean supports(AuthenticationToken token) {
		return token instanceof UsernamePasswordToken;
	}
}
2. MyRealm2

和MyRealm1完全一樣,只是Realm名字為b

3. MyRealm3

public class MyRealm3 implements Realm{
	public AuthenticationInfo getAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
		User user = new User("zhang","123");
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
				user,	//身份User型別 
				"123",		//憑據
				getName()	//Realm Name
		);
		return simpleAuthenticationInfo;
	}
	public String getName() {
		return "c";	//realm name為"c"
	}
	public boolean supports(AuthenticationToken token) {
		return token instanceof UsernamePasswordToken;
	}
}
和MyRealm1同名,但返回的Principal是User型別

4. ini配置(shiro-multirealm.ini)

[main]
realm1=chapter6.realm.MyRealm1
realm2=chapter6.realm.MyRealm2
realm3=chapter6.realm.MyRealm3
securityManager.realms=$realm1,$realm2,$realm3

5. 測試用例

因為我們的Realm 中沒有進行身份及憑據驗證,所以相當於身份驗證都是成功的,都將返回.

public class PrincialCollectionTest {
	@Test
	public void test(){
		//因為Realm裡沒有進行驗證,所以相當於每個Realm都身份驗證成功了
		login("classpath:chapter6/ini/shiro-multirealm.ini","zhang","123");
		Subject subject = SecurityUtils.getSubject();
		/*
		 * 我們可以直接呼叫subject.getPrincipal獲取PrimaryPrincipal(即所謂的第一個);
		 * 或者通過subject.getPrincipals獲取PrincipalCollection;然後通過其getPrimaryPrincipal獲取PrimaryPrincipal。
		 */
		Object primaryPrincipal1 = subject.getPrincipal();
		PrincipalCollection principalCollection = subject.getPrincipals();
		/*
		 * 返回第一個,但內部是Map儲存,所以可以理解為隨機返回
		 */
		Object primaryPrincipal2 = principalCollection.getPrimaryPrincipal();
		//但是因為多個Realm都返回了Principal,所以此處到底是哪個是不確定的
		Assert.assertEquals(primaryPrincipal1, primaryPrincipal2);
		/*
		 * 獲取所有身份驗證成功的Realm名字。返回a b c
		 */
		Set<String> realmNames = principalCollection.getRealmNames();
		System.out.println(realmNames);
		//==>[a, b, c]
		/*
		 * 因為MyRealm1和MyRealm2返回的憑據都是zhang,所以排重了
		 */
		//asList和asSet的結果是一樣的,因為將身份資訊轉換為Set/List,即使轉換為List,也是先轉換為Set再完成的。
		Set<Object> principals = principalCollection.asSet();
		System.out.println(principals);
		//==>[zhang, User {id=null, username=zhang, password=123, salt=null, locked=false}]
		/*
		 * 根據Realm名字獲取身份,因為Realm名字可以重複,所以可能多個身份,建議Realm名字儘量不要重複。
		 */
		Collection<User> users = principalCollection.fromRealm("c");
		System.out.println(users);
		//==>[User {id=null, username=zhang, password=123, salt=null, locked=false}]
	}
	public void login(String configFile,String username,String password){
		//1. 獲取SecurityManager工廠,此處使用Ini配置檔案初始化SecurityManager
		Factory<SecurityManager> factory = new IniSecurityManagerFactory(configFile);
		//2. 得到SecurityManager例項,並繫結給SecurityUtils
		SecurityManager securityManager = factory.getInstance();
		SecurityUtils.setSecurityManager(securityManager);
		//3. 得到Subject及建立使用者名稱/密碼身份驗證Token(即使用者身份/憑證)
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(username,password);
		subject.login(token);
	}
}

相關推薦

Realm相關物件 PrincipalCollection

之前使用過的(來點印象) login("classpath:shiro-authenticator-all-success.ini"); Subject subject = SecurityUtils.getSubject(); //得到一個身份集合,其包含了Realm

Realm相關物件 AuthorizationInfo

AuthorizationInfo用於聚合授權資訊的: public interface AuthorizationInfo extends Serializable { Collection<String> getRoles(); //獲取角色字串資訊

Realm相關物件 Realm

一、Realm 1. 定義實體及關係 即使用者-角色之間是多對多關係,角色-許可權之間是多對多關係;且使用者和許可權之間通過角色建立關係;在系統中驗證時通過許可權驗證,角色只是許可權集合,即所謂的顯示角色;其實許可權應該對應到資源(如選單、URL、頁面按鈕、Java 方法

----- Realm相關物件

6.1 Realm 【2.5 Realm】及【3.5 Authorizer】部分都已經詳細介紹過Realm了,接下來再來看一下一般真實環境下的Realm如何實現。 1、定義實體及關係 即使用者-角色之間是多對多關係,角色-許可權之間是多對多關係;且使用者和許可權之間通過

Realm相關物件——《跟我學Shiro》

ection;然後通過其getPrimaryPrincipal獲取PrimaryPrincipal。 Java程式碼   Set<String> realmNames = princialCollection.getRealmNames();   獲取所

Realm相關物件

6.1 Realm 【2.5 Realm】及【3.5 Authorizer】部分都已經詳細介紹過Realm了,接下來再來看一下一般真實環境下的Realm如何實現。 1、定義實體及關係 即使用者-角色之間是多對多關係,角色-許可權之間是多對多關係;且使用者和許可權之間通過

:循環結構

結構 不執行 三種 表達式 成了 不改變 條件 運算符 步驟 第六章:循環結構(二) 一. for 循環 1.循環結構的四個組成部分 (1). 初始部分:設置循環的初始狀態,比如我們設置記錄循環次數的變量 i 為 0 . (2). 循環體:重復執行的代碼 .

Scala入門到精通——節:類和物件

本節主要內容 1 類定義、建立物件 2 主構造器 3 輔助構造器 類定義、建立物件 //採用關鍵字class定義 class Person { //類成員必須初始化,否則會報錯 //這裡定義的是一個公有成員 var name:Strin

JVM垃圾收集器2

1、G1 說明: 從上圖來看,G1與CMS相比,僅在最後的"篩選回收"部分不同(CMS是併發清除),實際上G1回收器的整個堆記憶體的劃分都與其他收集器不同。 CMS需要配合ParNew,G1可單獨回收整個空間 原理: G1收集器將整個堆劃分為多個大小相等的Region G1

高等數學: 定積分的應用1定積分的應用 平面圖形的面積 立體體積

§6.1  定積分的元素法 一 再論曲邊梯形面積計算 設在區間上連續,且,求以曲線為曲邊,底為的曲邊梯形的面積。 1、化整為零 用任意一組分點   將區間分成 個小區間,其長度為 並記  相應地,曲邊梯形被劃分成個窄曲邊梯形,第個窄曲邊梯形的面積記為。 於是   2、以

《C++ Primer Plus》學習筆記—— 迴圈和關係表示式

程式設計練習 1.編寫一個要求使用者輸入兩個整數的程式。該程式將計算並輸出這兩個整數之間(包括這兩個整數)所有整數的和。這裡假設先輸入較小的整數。例如,如果使用者輸入的是2和9,則程式將指出2~9之間的所有整數的和為44. #include <iostream>

Shiro Realm相關物件

6.1 Realm 【2.5 Realm】及【3.5 Authorizer】部分都已經詳細介紹過Realm了,接下來再來看一下一般真實環境下的Realm如何實現。 1、定義實體及關係 即使用者-角色之間是多對多關係,角色-許可權之間是多對多關係;且使用者和許可

演算法導論 :堆排序 筆記堆、維護堆的性質、建堆、堆排序演算法、優先順序佇列、堆排序的程式碼實現

堆排序(heapsort) 像合併排序而不像插入順序,堆排序的執行時間為O(nlgn) 。像插入排序而不像合併排序,它是一種原地( in place) 排序演算法:在任何時候,陣列中只有常數個元素儲存在輸入陣列以外。 堆: (二叉)堆資料結構是一種陣列物件,它可以被視為一棵完全二叉樹。樹

強化學習RLAI讀書筆記Applications and Case Studiesalphago

強化學習(RLAI)讀書筆記第十六章Applications and Case Studies(alphago) 16.6 Mastering the Game of Go 16.6.1 AlphaGo 16.6.2 AlphaG

Essential c++ 練習類模板template class 知識點

知識點: 1、類模板形式 template< typename elemType> class T ,其中typename可以替換為class,寫成template< class elemType> class T。 呼叫形式:T< string>t1

概率統計: 樣本抽樣分佈

第六章  樣本及抽樣分佈 內容提要 一、總體 在數理統計中,研究物件的全體稱為總體,組成總體的每個元素稱為個體。總體常用一個隨機變數X表示。若X的分佈函式為F(x),稱F(x)為總體X的分佈函式。 二、樣本 設X是具有分佈函式F(x)的隨機變數,若是具有同一分佈函式F(x)

Oracle恢復內部原理介質恢復

介質恢復用在丟失或損壞資料檔案或者丟失了控制檔案的情形。介質恢復將還原的資料檔案恢復成當前資料檔案。還能夠恢復資料檔案異常離線時沒有來得及做檢查點操作丟失的變更。介質恢復使用歸檔日誌和聯機日誌。跟例項恢復不同的是,介質恢復必須由命令顯式呼叫。 6.1 什麼時候做介質恢復

Java Script 06 瀏覽器對象模型BOM

block alt display play java pla .cn img script Java Script 第06章 瀏覽器對象模型(BOM)

:循環結構

如何 如何使用 滿足 為什麽 發現 每日 生活 打印機 結構 第五章:循環結構(一) 1.什麽是循環結構 在日常生活中,會有很多需要反復執行的事情,比如:每一年的 4個季節,每一周的7天,每日的3餐,打印機每份文檔打印50 份,一圈跑道400米跑3圈,都是在反復執行的。 2

C語言程序設計次作業——循環結構2.

是什麽 絕對值 方法 程序設計 輸入一個數 系列 發生 自己 很好 (一)改錯題 序列求和:輸入一個正實數eps,計算序列部分和 1 - 1/4 + 1/7 - 1/10 + ... ,精確到最後一項的絕對值小於eps(保留6位小數)。   輸入輸出樣例:   Input