美文网首页
Authenticator及AutenticationStrat

Authenticator及AutenticationStrat

作者: tingshuo123 | 来源:发表于2018-08-23 22:41 被阅读29次

身份认证流程

流程图.png

流程如下:

  1. 通过Subject对象的login(token)方法登录,其会委托给Security Manager
  2. SecurityManager负责正的身份验证逻辑,它会委托给Authenticator进行身份验证;
  3. Autenticator才是真正的身份验证者,此处可自己实现。
  4. Autenticator可能会委托给 AuthenticationStrategy进行多 Realm 身份验证
  5. Autenticator 会把登录时传入的token对象,传给 Realm,验证成功后会返回AuthenticationInfo对象,此对象中包含用户的身份及凭证,如果认证失败会抛出AuthenticationException异常。此处可以配置多个 Realm,将按照相应的顺序及策略进行验证。

Authenticator

Authenticator有多种已实现的验证规则,可以通过 AuthenticationStrategy 接口指定,已经实现的验证规则有:

认证策略:

  • FirstSuccessfulStrategy:通过有一个Realm验证即通过验证,会返回第一个通过的Realm认证信息
  • AtLeastOneSuccessfulStrategy:同样一个通过即可,但是这个会返回所有Realm 身份验证成功的认证信息
  • AllSuccessfulStrategy:这个比较严厉,要通过所有的 Realm 验证才算成功,且返回所有的Realm 的认证信息

默认使用的是 AtLeastOneSuccessfulStrategy 验证策略;

代码实例

创建三个自定义的 Realm:

myRealm1: 用户名 / 密码为 admin/ad123 时成功,且返回身份 / 凭据为 admin/ad123;

myRealm2: 用户名 / 密码为 admin2/123 时成功,且返回身份 / 凭据为 admin2/ad123;

myRealm3: 用户名 / 密码为 admin/ad123 时成功,且返回身份 / 凭据为admin@163.com/123

myRealm1:

package shiro02;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.realm.Realm;

public class MyRealm1 implements Realm {

    @Override
    public String getName() {

        return "MyRealm1";
    }

    @Override
    public boolean supports(AuthenticationToken token) {

        return token instanceof UsernamePasswordToken;
    }

    @Override
    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 获取用户名跟密码
        String username = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());

        // 如果用户名错误
        if (!"admin".equals(username)) {
            throw new UnknownAccountException();
        }

        // 如果密码错误
        if (!"ad123".equals(password)) {
            throw new IncorrectCredentialsException();
        }

        // 验证通过
        return new SimpleAuthenticationInfo(username, password, getName());
    }

}

myRealm2 改变上面用户名与密码的字符串
myRealm3 将 return 语句改成 return new SimpleAuthenticationInfo(username + "@163.com", password, getName());

配置文件

shiro-authenticator-all-success.ini

#指定SecurityManager的authenticator实现
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
securityManager.authenticator=$authenticator

# 声明验证策略
allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy
# 指定策略
securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy

# 声明 realm
myRealm1=shiro02.MyRealm1
myRealm2=shiro02.MyRealm2
myRealm3=shiro02.MyRealm3
# 指定多个 realm
securityManager.realms=$myRealm1,$myRealm3
测试
package shiro02;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;

public class AuthenticatorTest {
    
    private void login(String configFile) {
        // 获取SecurityManager工厂
        Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory(
                configFile);

        // 获通过工厂获取SecurityManager实例
        SecurityManager securityManager = factory.getInstance();

        // 将实例绑定给SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);

        // 获取Subject
        Subject subject = SecurityUtils.getSubject();

        // 创建Token
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "ad123");

        // 登录(验证用户)
        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            // 验证失败
            e.printStackTrace();
        }

        if (subject.isAuthenticated()) {
            System.out.println("登录成功!!!");
        }
    }
    
    @Test
    public void testAllSuccessfulStrategyWithSuccess() {
        this.login("classpath:shiro-authenticator-all-success.ini");
        Subject subject = SecurityUtils.getSubject();
        
        // 得到身份集合,包含Realm验证成功的身份信息
        PrincipalCollection principalCollection = subject.getPrincipals();
        System.out.println(principalCollection.asList());
    }
}

相关文章

网友评论

      本文标题:Authenticator及AutenticationStrat

      本文链接:https://www.haomeiwen.com/subject/foqviftx.html