SpringShiro基础组件AuthenticationStrategy

导读:本篇文章讲解 SpringShiro基础组件AuthenticationStrategy,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

相关阅读

简介

鉴权策略的实现类帮助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;
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/4792.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!