shiro之AuthenticationStrategy认证策略

一、AuthenticationStrategy 是个无状态的组件,在认证过程中会进行如下4次调用

1.在所有Realm被调用之前

2.在调用Realm的getAuthenticationInfo方法之前

3.在调用Realm的getAuthenticationInfo 方法之后

4.在所有Realm被调用之后 即实现AuthenticationStrategy接口的类都要实现以下四个方法:beforeAllAttempts,beforeAttempt,afterAttempt,afterAllAttempts

二、对于多realm配置,Shiro有3中认证策略的具体实现

AtLeastOneSuccessfulStrategy(默认):只要有一个Realm验证成功即可,和FirstSuccessfulStrategy不同,返回所有Realm身份验证成功的认证信息;

FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略;

AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。

三测试用例

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)
{
    //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
    Factory<org.apache.shiro.mgt.SecurityManager> factory =
        new IniSecurityManagerFactory(configFile);

    //2、得到SecurityManager实例 并绑定给SecurityUtils
    org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
    SecurityUtils.setSecurityManager(securityManager);

    //3、得到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返回的身份一样所以输出时只返回一个,所以得到一个身份集合

转载于:https://my.oschina.net/u/2427561/blog/1517722

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值