Spring Shiro基础组件 AuthenticationStrategy

相关阅读

简介

鉴权策略的实现类帮助ModularRealmAuthenticator在可插拔Realm环境(PAM)中处理登录请求;

核心方法

/**
 * 鉴权过程预处理
 */
AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException;

/**
 * realm预鉴权处理
 */
AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException;

/**
 * realm后鉴权处理
 */
AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t)
        throws AuthenticationException;

/**
 * 鉴权过程后处理
 */
AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException;

使用场景

ModularRealmAuthenticator.doMultiRealmAuthentication方法中使用,代码如下:

protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {

    AuthenticationStrategy strategy = getAuthenticationStrategy();

    // 鉴权预处理,简单返回初始聚合结果
    AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);

    if (log.isTraceEnabled()) {
        log.trace("Iterating through {} realms for PAM authentication", realms.size());
    }

    // 遍历配置的realm
    for (Realm realm : realms) {

        try {
            // realm鉴权预处理
            aggregate = strategy.beforeAttempt(realm, token, aggregate);
        } catch (ShortCircuitIterationException shortCircuitSignal) {
            // 无需继续鉴权
            // Break from continuing with subsequnet realms on receiving 
            // short circuit signal from strategy
            break;
        }

        if (realm.supports(token)) {

            log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm);

            AuthenticationInfo info = null;
            Throwable t = null;
            try {
                info = realm.getAuthenticationInfo(token);
            } catch (Throwable throwable) {
                t = throwable;
                if (log.isDebugEnabled()) {
                    String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:";
                    log.debug(msg, t);
                }
            }

            // realm鉴权后处理,处理鉴权过程中抛出的异常以及合并鉴权后的账户数据
            aggregate = strategy.afterAttempt(realm, token, info, aggregate, t);

        } else {
            log.debug("Realm [{}] does not support token {}.  Skipping realm.", realm, token);
        }
    }

    // 鉴权后处理
    aggregate = strategy.afterAllAttempts(token, aggregate);

    return aggregate;
}

实现子类

public interface AuthenticationStrategy
    public abstract class AbstractAuthenticationStrategy implements AuthenticationStrategy
        public class AtLeastOneSuccessfulStrategy extends AbstractAuthenticationStrategy
        public class AllSuccessfulStrategy extends AbstractAuthenticationStrategy
        public class FirstSuccessfulStrategy extends AbstractAuthenticationStrategy

AbstractAuthenticationStrategy

简介

Shiro具体的鉴权策略实现的抽象基础实现;

核心方法

/**
 * 鉴权过程预处理
 * 简单返回支持跨realm聚合账户数据的SimpleAuthenticationInfo
 */
public AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException {
    return new SimpleAuthenticationInfo();
}

/**
 * realm预鉴权处理
 * 简单返回聚合账户数据
 */
public AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
    return aggregate;
}

/**
 * realm后鉴权处理
 * 聚合单个领域的账户数据的基本实现
 */
public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
    AuthenticationInfo info;
    if (singleRealmInfo == null) {
        info = aggregateInfo;
    } else {
        if (aggregateInfo == null) {
            info = singleRealmInfo;
        } else {
            info = merge(singleRealmInfo, aggregateInfo);
        }
    }

    return info;
}

/**
 * 聚合账户数据
 */
protected AuthenticationInfo merge(AuthenticationInfo info, AuthenticationInfo aggregate) {
    if( aggregate instanceof MergableAuthenticationInfo ) {
        ((MergableAuthenticationInfo)aggregate).merge(info);
        return aggregate;
    } else {
        throw new IllegalArgumentException( "Attempt to merge authentication info from multiple realms, but aggregate " +
                  "AuthenticationInfo is not of type MergableAuthenticationInfo." );
    }
}

/**
 * 鉴权过程后处理
 * 简单返回聚合账户数据
 */
public AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
    return aggregate;
}

AtLeastOneSuccessfulStrategy

简介

只要有一个配置的Realm鉴权通过则判定登录成功,保留所有鉴权通过的账号数据;

核心方法

/**
 * 鉴权过程后处理
 * 如果聚合账户数据为空,则表示所有realm鉴权失败
 */
public AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
    //we know if one or more were able to successfully authenticate if the aggregated account object does not
    //contain null or empty data:
    if (aggregate == null || isEmpty(aggregate.getPrincipals())) {
        throw new AuthenticationException("Authentication token of type [" + token.getClass() + "] " +
                "could not be authenticated by any configured realms.  Please ensure that at least one realm can " +
                "authenticate these tokens.");
    }

    return aggregate;
}

AllSuccessfulStrategy

简介

所有配置的Realm鉴权通过则判定登录成功;

核心方法

/**
 * realm预鉴权处理
 * 校验当前realm是否支持该token
 */
public AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
    if (!realm.supports(token)) {
        String msg = "Realm [" + realm + "] of type [" + realm.getClass().getName() + "] does not support " +
                " the submitted AuthenticationToken [" + token + "].  The [" + getClass().getName() +
                "] implementation requires all configured realm(s) to support and be able to process the submitted " +
                "AuthenticationToken.";
        throw new UnsupportedTokenException(msg);
    }

    return info;
}

/**
 * realm后鉴权处理
 * 聚合单个领域的账户数据前会额外校验
 *   1. 异常信息不为null,则立即抛出异常
 *   2. 账户数据为null,则立即抛出异常
 */
public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo info, AuthenticationInfo aggregate, Throwable t)
        throws AuthenticationException {
    // 异常信息不为null
    if (t != null) {
        if (t instanceof AuthenticationException) {
            //propagate:
            throw ((AuthenticationException) t);
        } else {
            String msg = "Unable to acquire account data from realm [" + realm + "].  The [" +
                    getClass().getName() + " implementation requires all configured realm(s) to operate successfully " +
                    "for a successful authentication.";
            throw new AuthenticationException(msg, t);
        }
    }
    // 账户数据为null
    if (info == null) {
        String msg = "Realm [" + realm + "] could not find any associated account data for the submitted " +
                "AuthenticationToken [" + token + "].  The [" + getClass().getName() + "] implementation requires " +
                "all configured realm(s) to acquire valid account data for a submitted token during the " +
                "log-in process.";
        throw new UnknownAccountException(msg);
    }

    log.debug("Account successfully authenticated using realm [{}]", realm);

    // If non-null account is returned, then the realm was able to authenticate the
    // user - so merge the account with any accumulated before:
    merge(info, aggregate);

    return aggregate;
}

FirstSuccessfulStrategy

简介

只要有一个配置的Realm鉴权通过则判定登录成功,只保留第一个鉴权通过的账户数据;

核心方法

// 停止标识
private boolean stopAfterFirstSuccess;

/**
 * 鉴权过程预处理
 * 简单返回null
 */
public AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException {
    return null;
}

/**
 * realm预鉴权处理
 * 如果设置停止标识,那么只要鉴权通过则抛出ShortCircuitIterationException异常
 */
public AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
    if (getStopAfterFirstSuccess() && aggregate != null && !isEmpty(aggregate.getPrincipals())) {
        throw new ShortCircuitIterationException();
    }
    return aggregate;
}

/**
 * 聚合账户数据
 */
protected AuthenticationInfo merge(AuthenticationInfo info, AuthenticationInfo aggregate) {
    // 如果聚合结果有效则直接返回
    if (aggregate != null && !isEmpty(aggregate.getPrincipals())) {
        return aggregate;
    }
    return info != null ? info : aggregate;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值