Shiro 學習筆記(3) 自定義 Realm

2021-07-22 19:04:04 字數 4178 閱讀 1413

自定義的 realm 使得我們使用安全資料來源更加靈活,在自定義的 realm 中,我們就可以自己控制認證和授權的邏輯了。同時我們還簡單介紹了一下在多個 realm 同時存在的情況下,我們可以配置我們的認證策略來滿足我們的需求。

前面兩節我們已經介紹過 inirealm 和 jdbcrealm,這一節我們介紹自定義的 realm 實現我們自己的安全資料來源。

這種方式實現的 realm 僅只能實現認證操作,並不能實現授權操作。

**:

public

class

maprealm

implements

realm

/*** 返回乙個唯一的 realm 名字

*@return

*/public string getname()

/*** 判斷此 realm 是否支援此 token

*@param authenticationtoken

*@return

*/public

boolean

supports(authenticationtoken authenticationtoken)

/*** 根據 token 獲取認證資訊

*@param authenticationtoken

*@return

*@throws authenticationexception

*/public authenticationinfo getauthenticationinfo(authenticationtoken authenticationtoken) throws authenticationexception else

if(!password.equals(users.get(username)))

return

new ******authenticationinfo(username,password,getname());

}}

接下來我們要在 shiro.ini 檔案中宣告我們要是用的這個 realm。

[main]

# 宣告了我們自己定義的乙個 realm

mymaprealm=com

.liwei

.realm

.maprealm

# 將我們自己定義的 realm 注入到 securitymanager 的 realms 屬性中去

securitymanager.realms=$mymaprealm

示例**:

public

class

mystaticrealm

extends

authorizingrealm

/*** 用於認證

*@param token

*@return

*@throws authenticationexception

*/@override

protected authenticationinfo dogetauthenticationinfo(authenticationtoken token) throws authenticationexception else

if(!"123456".equals(password))

return

new ******authenticationinfo("liweipower@gmail","123456",getname());

}}

下面這一行說明的事實是很重要的:

dogetauthenticationinfo()方法中須要返回乙個正確的******authenticationinfo物件,這樣 shiro 就會和subjectlogin()方法中傳入的 token 資訊進行比對,完成認證的操作。

然後我們在 shiro.ini 中也要配置這個自定義的 realm:

**:

[main]

mystaticrealm=com

.liwei

.realm

.mystaticrealm

securitymanager.realms=$mystaticrealm

這時候,我們會有乙個疑問,securitymanager 的屬性既然是 realms,說明可以設定若干個 realm,它們認證的順序是如何的呢。

shiro 會按照我們宣告的順序,依次驗證。在使用了 ini 檔案啟動 shiro 的方式中,inirealm 在 shiro 中是預設使用的(我個人覺得應該是第乙個使用的,即使在我們不宣告的情況下)。

那麼對於若干個 realm,shiro 提供了一種配置方式,讓我們來決定在多個 reaml 同時宣告的情況下,採用哪些 realm 返回的認證資訊的方式,這就是我們的認證策略。

認證策略主要有以下三種:

1、firstsuccessfulstrategy:只要有乙個 realm 驗證成功即可,只返回第乙個 realm 身份驗證成功的認證資訊,其他的忽略;

2、atleastonesuccessfulstrategy: (這是預設使用的認證策略,即在不配置情況下 shiro 所採用的認證策略)只要有乙個 realm 驗證成功即可, 和 firstsuccessfulstrategy 不同,返回所有 realm 身份驗證成功的認證資訊;

3、allsuccessfulstrategy:所有 realm 驗證成功才算成功,且返回所有 realm 身份驗證成功的認證資訊,如果有乙個失敗就失敗了。

配置示例:

# 配置認證策略

allsuccessfulstrategy=org.apache

.shiro

.authc

.pam

.allsuccessfulstrategy

securitymanager.authenticator

.authenticationstrategy=$allsuccessfulstrategy

配置好以後,我們可以通過以下的方法來驗證我們剛剛配置的 shiro 的認證策略。

currentsubject.login(token);

principalcollection ps = currentsubject.getprincipals();

system.out

.println(ps.aslist());

system.out

.println(ps.getrealmnames());

system.out

.println(currentsubject.getprincipals());

自定義 realm 就介紹到這裡了。自定義 realm 是很重要的,特別是 extends authorizingrealm 這種方式。

學習到這裡想再強調一下 extends authorizingrealm 這種方式覆寫的 dogetauthenticationinfo() 方法,一開始我不是很明白,這個方法到底是做什麼的,就上面我們舉例,我想再解釋一下。

一般地,我們從引數 authenticationtoken 物件中取出使用者填寫的使用者名稱和密碼資訊,這個 token 其實就是 subject 使用 login() 方法中傳入的 usernamepasswordtoken 物件,我們通過這個 usernamepasswordtoken 物件獲得使用者填寫的使用者名稱和密碼,然後我們應該通過使用者的使用者名稱去資料庫查詢資料庫是否有這個使用者名稱,如果沒有,丟擲乙個使用者名稱不存在異常;如果使用者名稱存在,返回乙個使用者物件(帶密碼的),再用資料庫返回的密碼資料和使用者填寫的密碼資料進行比對,如果錯誤,就丟擲異常,如果正確,就要把正確的使用者名稱和密碼資訊封裝成乙個 ******authenticationinfo 物件返回,這才是乙個比較完整並且正確的流程。

另外再補充一下,我在上面的例子中說到「使用者填寫的使用者名稱和密碼」是一種為了方便理解的說法。下面介紹官方正確的說法。

principals:身份,即主體的標識屬性,可以是任何東西,如使用者名稱、郵箱等,唯一即可。乙個主體可以有多個 principals, 但只有乙個 primary principals, 一般是使用者名稱/密碼/手機號。

credentials:證明/憑證,即只有主體知道的安全值,如密碼/數字證書等。

最常見的 principals 和 credentials 組合就是使用者名稱/密碼了。

Shiro學習筆記之自定義Realm實現認證和授權

我們之前通過配置檔案去獲取使用者角色許可權的資訊,但是有些時候希望從資料庫中讀取許可權資訊,此時就需要用到自定義realm。public class user public void setusername string username public string getpassword publ...

Shiro 自定義角色 認證

由於shiro filterchaindefinitions中 roles預設是and,user,roles system,general 比如 roles system,general 表示同時需要 system 和 general 2個角色才通過認證 所以需要自定義 繼承 authorizati...

Shiro實現自定義filter

當使用者訪問匹配規則的url時觸發的過濾器,通常我們都繼承如下幾個類並重寫方法完成自定義過濾器 概述 這個類是遊客訪問即無需登入訪問的資源時進入的過濾器 概述 該方法如果返回true則可以訪問,返回false則不能訪問 引數request 關於這個請求的請求物件 引數response 關於這個請求的...