AuthenticationStrategy在验证过程中到底做了什么

本文深入探讨了Shiro的AuthenticationStrategy在验证过程中的作用,重点解析了beforeAllAttempts、beforeAttemps、afterAttempt和afterAllAttempts四个关键方法的功能。通过自定义Strategy,可以实现特定的异常处理和认证逻辑,确保认证流程的灵活性和可控性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Shiro getAuthenticationInfo()中抛出异常, 全局异常处理却收不到自己抛出的异常中, 介绍了通过覆盖AuthenticationStrategy的afterAttempt方法, 更改Shiro的异常抛出逻辑.

本文介绍AuthenticationStrategy在验证过程中到底做了什么

想要弄清Strategy, 就要关注在ModularRealmAuthenticator.doMultiRealmAuthentication()的aggregate

protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, 
                        AuthenticationToken token) {		
				// 获取验证策略
        AuthenticationStrategy strategy = getAuthenticationStrategy();
        **AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);**			
				// 循环遍历realm
        for (Realm realm : realms) {
						// 
            try {
                **aggregate = strategy.beforeAttempt(realm, token, aggregate);**
            } catch (ShortCircuitIterationException shortCircuitSignal) {
                break;
            }

            if (realm.supports(token)) {
                AuthenticationInfo info = null;
                Throwable t = null;
                try {
										**// 这里调用了自定义Realm的getAuthenticationInfo方法**
                    **info = realm.getAuthenticationInfo(token);**
                } catch (Throwable throwable) {... }
                **aggregate = strategy.afterAttempt(realm, token, info, aggregate, t);**

            } else {...}
        }
        **aggregate = strategy.afterAllAttempts(token, aggregate);**

        return aggregate;
    

首先, 根据字面意思, aggregate释义"集合, 集合体".

其次, 在上述方法的执行过程中, aggregate起到了将从realm中返回的认证信息(即AuthenticationInfo)组成一个大集合的作用.

上述代码块中, 标注黑体的地方就是Strategy发挥作用的地方, 下面进行一一解析.

beforeAllAttempts 方法:

new并返回了一个 空的SimpleAuthenticationInfo

public AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException {
    return new SimpleAuthenticationInfo();
}

beforeAttemps方法:

看似传了一大波参数, 实际上就是将aggregate原封不动地返回

public AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
    return aggregate;
}

afterAttempt方法,

传入了当前Realm, 在Realm中抛出的异常, 以及两个AuthenticationInfo.

两个Info解释: 假设目前已经有n个Realm执行, 那么aggregateInfo就是前n-1个Realm中返回Info的聚合, singleRealmInfo 则是第n个Realm返回的Info.

@Override
public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
    if (t != null && t instanceof AuthenticationException){
        throw (AuthenticationException) t;
    }
    return super.afterAttempt(realm, token, singleRealmInfo, aggregateInfo, t);
}

继续查看父类中的afterAttemp:

public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
        AuthenticationInfo info;
        if (singleRealmInfo == null) { // 如果当前Info为null, 那就直接不聚合该Info
            info = aggregateInfo;
        } else { // 否则对该Info进行聚合
            if (aggregateInfo == null) {  
                info = singleRealmInfo;// 如果之前聚合过的Info为空, 那么直接设当前Info为聚合Info
            } else {
                info = merge(singleRealmInfo, aggregateInfo); // 否则将两个info进行聚合
            }
 }

到这里, 大概可以明白: afterAttempt方法的作用就是: 对Realm中的异常进行处理, 聚合新的Info.

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;
}

afterAllAttempts 方法 :

判断aggregate是否为null或Empty, ...

说白了就是: 处理当aggregate异常的状况

public AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
    if (aggregate == null ||isEmpty(aggregate.getPrincipals())) {
        throw new AuthenticationException("...");
    }
    return aggregate;
}

当且仅当上述四个方法执行过程中没有抛出任何异常, doMultiRealmAuthentication()方法才能将最终聚合的Info成功返回!

在实际的开发中, 当然可以通过对这些方法进行自定义, 实现自己想要的逻辑! 具体流程的话, 可以看看: Shiro getAuthenticationInfo()中抛出异常, 全局异常处理却收不到自己抛出的异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值