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返回的身份同样因此输出时只返回一个,因此获得一个身份集合