小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

第四章:Shiro的身份認(rèn)證(Authentication)

 wayne_liberary 2014-08-07

Authentication概述

n概述

  Authentication 是指身份驗(yàn)證的過(guò)程——即證明一個(gè)用戶實(shí)際上是不是他們所說(shuō)的他們是誰(shuí)。也就是說(shuō)通過(guò)提交用戶的身份和憑證給Shiro,以判斷它們是否和應(yīng)用程序預(yù)期的相匹配。

n基本概念

1:Principals(身份):是Subject 的‘identifying attributes(標(biāo)識(shí)屬性)’。比如我們登錄提交的用戶名。

2:Credentials(憑證):通常是只被Subject 知道的秘密值,它用來(lái)作為一種起支持作用的證據(jù),此證據(jù)事實(shí)上包含著所謂的身份證明。比如我們登錄提供的密碼

 

n認(rèn)證的基本步驟

1. 收集Subjects 提交的Principals(身份)和Credentials(憑證);

2. 提交Principals(身份)和Credentials(憑證)進(jìn)行身份驗(yàn)證;

3. 如果提交成功,則允許訪問(wèn),否則重新進(jìn)行身份驗(yàn)證或者阻止訪問(wèn)。

 

認(rèn)證樣例

n使用用戶名/密碼的樣例

UsernamePasswordToken token = new UsernamePasswordToken(username, password);

token.setRememberMe(true);

  樣例使用UsernamePasswordToken 來(lái)支持最常見(jiàn)的用戶名/密碼的身份驗(yàn)證方法。這是Shiro的org.apache.shiro.authc.AuthenticationToken 的接口,是Shiro 代表提交的Principals(身份)和Credentials(憑證)的身份驗(yàn)證系統(tǒng)所使用的基本接口的一個(gè)實(shí)現(xiàn)。

n提交用戶名/密碼進(jìn)行認(rèn)證

Subject currentUser = SecurityUtils.getSubject();

currentUser.login(token);

n處理認(rèn)證成功和失敗

  如果認(rèn)證成功,會(huì)沒(méi)有返回,也沒(méi)有例外,通過(guò)。

  如果認(rèn)證失敗,會(huì)拋出例外,你可以在程序中捕獲并處理,如下示例:

 

try {

  currentUser.login(token);

} catch ( UnknownAccountException uae ) { …

} catch ( IncorrectCredentialsException ice ) { …

} catch (LockedAccountException lae ) { …

} catch (ExcessiveAttemptsException eae ) { …

} … catch your own …

nlogout(注銷)

  currentUser.logout();

  當(dāng)你調(diào)用logout,任何現(xiàn)有的Session 都將會(huì)失效,而且任何身份都將會(huì)失去關(guān)聯(lián)(例如,在Web 應(yīng)用程序中,RememberMe cookie 也將被刪除)。在Subject 注銷后,該Subject的實(shí)例被再次認(rèn)為是匿名的,當(dāng)然,除了Web 應(yīng)用程序。

  注意:由于在Web 應(yīng)用程序記住身份往往是依靠Cookies,然而Cookies 只能在Response 被committed 之前被刪除,所以強(qiáng)烈建議在調(diào)用subject.logout()后立即將終端用戶重定向到一個(gè)新的視圖或頁(yè)面。

  這樣能夠保證任何與安全相關(guān)的Cookies 都能像預(yù)期的一樣被刪除。這是HTTP cookies 的功能限制,而不是Shiro的。

 

RememberedAuthenticated

nRemembered(記住我)

  一個(gè)記住我的Subject 不是匿名的,是有一個(gè)已知的身份ID(也就是subject.getPrincipals()是非空的)。但是這個(gè)被記住的身份ID 是在之前的session 中被認(rèn)證的。如果subject.isRemembered()返回true,則Subject 被認(rèn)為是被記住的。

 

nAuthenticated(已認(rèn)證)

  一個(gè)已認(rèn)證的Subject 是指在當(dāng)前Session 中被成功地驗(yàn)證過(guò)了(也就是說(shuō),login方法被調(diào)用并且沒(méi)有拋出異常)。如果subject.isAuthenticated()返回true 則認(rèn)為Subject 已通過(guò)驗(yàn)證。

 

n注意他們是互斥的

  Remembered 和Authenticated 是互斥的——若其中一個(gè)為真則另一個(gè)為假,反之亦然

 

認(rèn)證順序

 

nStep 1:應(yīng)用程序代碼調(diào)用Subject.login 方法,傳遞創(chuàng)建好的包含終端用戶的Principals(身份)和Credentials(憑證)的AuthenticationToken 實(shí)例。
nStep 2:Subject實(shí)例,通常是DelegatingSubject(或子類)委托應(yīng)用程序的SecurityManager通過(guò)調(diào)用securityManager.login(token)開(kāi)始真正的驗(yàn)證。
nStep3:SubjectManager 接收token 以及簡(jiǎn)單地委托給內(nèi)部的Authenticator 實(shí)例通過(guò)調(diào)用authenticator.authenticate(token)。這通常是一個(gè)ModularRealmAuthenticator 實(shí)例,支持在身份驗(yàn)證中協(xié)調(diào)一個(gè)或多個(gè)Realm 實(shí)例。
n
nStep 4:如果應(yīng)用程序中配置了一個(gè)以上的Realm,ModularRealmAuthenticator 實(shí)例將利用配置好的AuthenticationStrategy 來(lái)啟動(dòng)Multi-Realm 認(rèn)證嘗試。在Realms 被身份驗(yàn)證調(diào)用之前,期間和以后,AuthenticationStrategy 被調(diào)用使其能夠?qū)γ總€(gè)Realm 的結(jié)果作出反應(yīng)。
n
nStep 5:每個(gè)配置的Realm 用來(lái)幫助看它是否支持提交的AuthenticationToken。如果支持,那么支持Realm 的getAuthenticationInfo 方法將會(huì)伴隨著提交的token 被調(diào)用。getAuthenticationInfo 方法有效地代表一個(gè)特定Realm 的單一的身份驗(yàn)證嘗試。
初識(shí)自定義 Realm
n這里先來(lái)個(gè)例子,認(rèn)識(shí)一下:

public class MyRealm extends AuthorizingRealm{

  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

  String userName = (String) getAvailablePrincipal(principals);

  //通過(guò)用戶名去獲得用戶的所有資源,并把資源存入info中

  SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

  Set<String> s = new HashSet<String>();

  s.add("p1");  s.add("p2"); info.setStringPermissions(s);

  Set<String> r = new HashSet<String>();

  r.add("r1"); r.add("r2"); info.setRoles(r);

  return info;}

  protected AuthenticationInfo doGetAuthenticationInfo(

  AuthenticationToken token) throws AuthenticationException {

  //token中儲(chǔ)存著輸入的用戶名和密碼

  UsernamePasswordToken upToken = (UsernamePasswordToken)token;

  String username = upToken.getUsername();

  String password = String.valueOf(upToken.getPassword());

  //通常是與數(shù)據(jù)庫(kù)中用戶名和密碼進(jìn)行比對(duì),這里就省略了

  //比對(duì)成功則返回info,比對(duì)失敗則拋出對(duì)應(yīng)信息的異常AuthenticationException

  SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password .toCharArray(),getName());

  return info;  }}

 

 

配置多個(gè)Realm

n上面的例子可以作為第一個(gè)Realm
n再?gòu)?fù)制一份,定義為MyRealm2,在返回user前添加拋出一個(gè)例外,表示認(rèn)真沒(méi)有通過(guò),如下:

if(username.equals("javass")){

  throw new AuthenticationException("MyRealm2 認(rèn)證失敗");

}

SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password .toCharArray(),getName());

n在配置文件里面添加Realm的定義

myRealm1=cn.javass.hello.MyRealm

myRealm2=cn.javass.hello.MyRealm2

 

由于有多個(gè)realm,一般就需要配置AuthenticationStrategy了,而AuthenticationStrategy是跟Authenticator(認(rèn)證器)相關(guān)的。

 

 

n配置Authenticator和AuthenticationStrategy

authenticator = org.apache.shiro.authc.pam.ModularRealmAuthenticator

authcStrategy = org.apache.shiro.authc.pam.AllSuccessfulStrategy

authenticator.authenticationStrategy = $authcStrategy

authenticator.realms=$myRealm2,$myRealm1

n當(dāng)然,你可以擴(kuò)展并實(shí)現(xiàn)自己的Authenticator,一般沒(méi)有必要
n最后把Authenticator設(shè)置給securityManager

  securityManager.authenticator = $authenticator

n關(guān)于AuthenticationStrategy的配置,有三種:

AtLeastOneSuccessfulStrategy :如果一個(gè)(或更多)Realm 驗(yàn)證成功,則整體的嘗試被認(rèn)為是成功的。如果沒(méi)有一個(gè)驗(yàn)證成功,則整體嘗試失敗。

FirstSuccessfulStrategy 只有第一個(gè)成功地驗(yàn)證的Realm 返回的信息將被使用。所有進(jìn)一步的Realm 將被忽略。如果沒(méi)有一個(gè)驗(yàn)證成功,則整體嘗試失敗

AllSucessfulStrategy 為了整體的嘗試成功,所有配置的Realm 必須驗(yàn)證成功。如果沒(méi)有一個(gè)驗(yàn)證成功,則整體嘗試失敗。

 

ModularRealmAuthenticator 默認(rèn)的是AtLeastOneSuccessfulStrategy

 

 

n自定義自己的AuthenticationStrategy,通常是擴(kuò)展自AbstractAuthenticationStrategy,示例如下:

public class MyAuthenticationStrategy extends AbstractAuthenticationStrategy{

  public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {

  if(realm.getName().equals("myRealm2")){

  if(singleRealmInfo==null || singleRealmInfo.getPrincipals()==null){

  throw new AuthenticationException("主戰(zhàn)認(rèn)證未通過(guò)");

  }

  }

return super.afterAttempt(realm, token, singleRealmInfo, aggregateInfo, t);

  }

}

至于具體覆蓋擴(kuò)展什么方法,需要根據(jù)你具體的策略來(lái)定。

 

 

多個(gè)Realm的驗(yàn)證順序

n概述

  非常重要的一點(diǎn)是:ModularRealmAuthenticator 將與Realm 實(shí)例以迭代的順序進(jìn)行交互。

  在SecurityManager 中已經(jīng)配置好了ModularRealmAuthenticator 對(duì)Realm實(shí)例的訪問(wèn)。當(dāng)執(zhí)行一個(gè)認(rèn)證嘗試時(shí),它將會(huì)遍歷該集合,并對(duì)每一個(gè)支持提交AuthenticationToken 的Realm 調(diào)用Realm 的getAuthenticationInfo 方法

n隱式排列

  當(dāng)你配置多個(gè)realm的時(shí)候,處理的順序默認(rèn)就是你配置的順序。

  這種情況通常就是只定義了realm,而沒(méi)有配置securityManager的realms

n顯示排列

  也就是顯示的配置securityManager.realms,那么執(zhí)行的順序就是你配置該值的realm的順序。

  通常更推薦顯示排列。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多