1、AuthenticationStrategy 是個無狀態的組件,在認證過程當中會進行以下4次調用git
1.在全部Realm被調用以前github
2.在調用Realm的getAuthenticationInfo方法以前apache
3.在調用Realm的getAuthenticationInfo 方法以後ide
4.在全部Realm被調用以後 即實現AuthenticationStrategy接口的類都要實現如下四個方法:beforeAllAttempts,beforeAttempt,afterAttempt,afterAllAttempts測試
2、對於多realm配置,Shiro有3中認證策略的具體實現spa
AtLeastOneSuccessfulStrategy(默認):只要有一個Realm驗證成功便可,和FirstSuccessfulStrategy不一樣,返回全部Realm身份驗證成功的認證信息;code
FirstSuccessfulStrategy:只要有一個Realm驗證成功便可,只返回第一個Realm身份驗證成功的認證信息,其餘的忽略;token
AllSuccessfulStrategy:全部Realm驗證成功纔算成功,且返回全部Realm身份驗證成功的認證信息,若是有一個失敗就失敗了。接口
三測試用例ip
1.ini配置
[main] #指定securityManager的authenticator實現 authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator securityManager.authenticator=$authenticator #指定securityManager.authenticator的authenticationStrategy allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1 myRealm3=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm3 securityManager.realms=$myRealm1,$myRealm3
2.Realm定義
public class MyRealm1 implements Realm { @Override public String getName() { return "myrealm1"; } @Override public boolean supports(AuthenticationToken token) { return token instanceof UsernamePasswordToken; //僅支持UsernamePasswordToken類型的Token } @Override public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String)token.getPrincipal(); //獲得用戶名 String password = new String((char[])token.getCredentials()); //獲得密碼 if(!"zhang".equals(username)) { throw new UnknownAccountException(); //若是用戶名錯誤 } if(!"123".equals(password)) { throw new IncorrectCredentialsException(); //若是密碼錯誤 } //若是身份認證驗證成功,返回一個AuthenticationInfo實現; return new SimpleAuthenticationInfo(username, password, getName()); } }
public class MyRealm3 implements Realm { @Override public String getName() { return "myrealm3"; } @Override public boolean supports(AuthenticationToken token) { return token instanceof UsernamePasswordToken; //僅支持UsernamePasswordToken類型的Token } @Override public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String)token.getPrincipal(); //獲得用戶名 String password = new String((char[])token.getCredentials()); //獲得密碼 if(!"zhang".equals(username)) { throw new UnknownAccountException(); //若是用戶名錯誤 } if(!"123".equals(password)) { throw new IncorrectCredentialsException(); //若是密碼錯誤 } //若是身份認證驗證成功,返回一個AuthenticationInfo實現; return new SimpleAuthenticationInfo(username + "@163.com", password, getName()); } }
public class MyRealm4 implements Realm { @Override public String getName() { return "myrealm4"; } @Override public boolean supports(AuthenticationToken token) { return token instanceof UsernamePasswordToken; //僅支持UsernamePasswordToken類型的Token } @Override public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String)token.getPrincipal(); //獲得用戶名 String password = new String((char[])token.getCredentials()); //獲得密碼 if(!"zhang".equals(username)) { throw new UnknownAccountException(); //若是用戶名錯誤 } if(!"123".equals(password)) { throw new IncorrectCredentialsException(); //若是密碼錯誤 } //若是身份認證驗證成功,返回一個AuthenticationInfo實現; return new SimpleAuthenticationInfo(username, password, getName()); } }
3.登陸邏輯
private void login(String configFile) { //一、獲取SecurityManager工廠,此處使用Ini配置文件初始化SecurityManager Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory(configFile); //二、獲得SecurityManager實例 並綁定給SecurityUtils org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); //三、獲得Subject及建立用戶名/密碼身份驗證Token(即用戶身份/憑證) Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123"); subject.login(token); }
4.測試AllSuccessfulStrategy成功:
@Test public void testAllSuccessfulStrategyWithSuccess() { login("classpath:shiro-authenticator-all-success.ini"); Subject subject = SecurityUtils.getSubject(); //獲得一個身份集合,其包含了Realm驗證成功的身份信息 PrincipalCollection principalCollection = subject.getPrincipals(); Assert.assertEquals(2, principalCollection.asList().size()); }
總結:PrincipalCollection principalCollection = subject.getPrincipals(); 由於myRealm1和myRealm4返回的身份同樣因此輸出時只返回一個,因此獲得一個身份集合