shiro之AuthenticationStrategy認證策略

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返回的身份同樣因此輸出時只返回一個,因此獲得一個身份集合

相關文章
相關標籤/搜索