手机短信登录、邮箱登录、QQ 登录都想要,2024年这些高频面试知识点最后再发一次

  1. 如果当前 Realm 认证结果不为 null,并且聚合结果为 null,那么就把当前 Realm 的认证结果赋值给 info 并返回。

  2. 如果当前 Realm 认证结果不为 null,并且聚合结果也不为 null,则将两者合并之后返回。

2.1.4 afterAllAttempts

public AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {

return aggregate;

}

这里直接把聚合结果返回,没啥好说的。

2.1.5 merge

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.” );

}

}

merge 其实就是调用 aggregate 的 merge 方法进行合并,正常情况下我们使用的 SimpleAuthenticationInfo 就是 MergableAuthenticationInfo 的子类,所以这里合并没问题。

2.2 AtLeastOneSuccessfulStrategy

2.2.1 beforeAllAttempts

同 2.1.1 小节。

2.2.2 beforeAttempt

同 2.1.2 小节。

2.2.3 afterAttempt

同 2.1.3 小节。

2.2.4 afterAllAttempts

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;

}

这里的逻辑很明确,就是当聚合结果为空就直接抛出异常。

2.2.5 merge

同 2.1.5 小节。

2.2.6 小结

结合 2.1 小节的内容,我们来梳理一下 AtLeastOneSuccessfulStrategy 的功能。

  1. 首先,系统调用 beforeAllAttempts 方法会获取一个空的 SimpleAuthenticationInfo 对象作为聚合结果 aggregate。

  2. 接下来遍历所有的 Realm,在每个 Realm 调用之前先调用 beforeAttempt 方法,该方法只会原封不动的返回聚合结果 aggregate。

  3. 调用每个 Realm 的 getAuthenticationInfo 方法进行认证。

  4. 调用 afterAttempt 方法对认证结果进行聚合处理。如果当前 Realm 认证返回 null,就把聚合结果返回;如果当前 Realm 认证不返回 null,就把 当前的 Realm 的认证结果和 aggregate 进行合并(aggregate 不会为 null,因为 beforeAllAttempts 方法中固定返回空对象)。

这就是 AtLeastOneSuccessfulStrategy 的认证策略。可以看到:如果只有一个 Realm 认证成功,那么正常返回,如果有多个 Realm 认证成功,那么返回的用户信息中将包含多个认证用户信息。

可以通过如下方式获取返回的多个用户信息:

Subject subject = SecurityUtils.getSubject();

subject.login(token);

PrincipalCollection principals = subject.getPrincipals();

List list = principals.asList();

for (Object o : list) {

System.out.println("o = " + o);

}

subject.getPrincipals() 方法可以获取多个认证成功的凭证。

2.3 AllSuccessfulStrategy

2.3.1 beforeAllAttempts

同 2.1.1 小节。

2.3.2 beforeAttempt

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 是否支持当前 token。

这块的代码我觉得略奇怪,为啥其他认证策略都不检查,只有这里检查?感觉像是一个 BUG。有懂行的小伙伴可以留言讨论下这个问题。

2.3.3 afterAttempt

public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo info, AuthenticationInfo aggregate, Throwable t)

throws AuthenticationException {

if (t != null) {

if (t instanceof AuthenticationException) {

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

}

}

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

}

merge(info, aggregate);

return aggregate;

}

如果当前认证出错了,或者认证结果为 null,就直接抛出异常(因为这里要求每个 Realm 都认证成功,但凡有一个认证失败了,后面的就没有必要认证了)。

如果一切都 OK,就会结果合并然后返回。

2.3.4 afterAllAttempts

同 2.1.4 小节。

2.3.5 merge

同 2.1.5 小节。

2.3.6 小结

这种策略比较简单,应该不用多做解释吧。如果有多个 Realm 认证成功,这里也是会返回多个 Realm 的认证信息的,获取多个 Realm 的认证信息同上一小节。

2.4 FirstSuccessfulStrategy

2.4.1 beforeAllAttempts

public AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException {

return null;

}

不同于前面,这里直接返回了 null。

2.4.2 beforeAttempt

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

if (getStopAfterFirstSuccess() && aggregate != null && !isEmpty(aggregate.getPrincipals())) {

throw new ShortCircuitIterationException();

}

return aggregate;

}

这里的逻辑是这样,如果 getStopAfterFirstSuccess() 方法返回 true,并且当前认证结果的聚合不为空,那么就直接抛出异常,一旦抛出异常,就会跳出当前循环,也就是不会调用当前 Realm 进行认证操作了。这个思路和 FirstSuccessfulStrategy 名字基本上是契合的。

不过这里有一个方法 getStopAfterFirstSuccess(),看名字就知道是否在第一次成功后停止认证,默认情况下,该变量为 false,即即使第一次认证成功后,也还是会继续后面 Realm 的认证。

如果我们希望当第一次认证成功后,后面的 Realm 就不认证了,那么记得配置该属性为 true。

2.4.3 afterAttempt

同 2.1.3 小节。

2.4.4 afterAllAttempts

同 2.1.4 小节。

2.4.5 merge

不知道小伙伴们是否还记得 merge 方法是在哪里调用的,回顾 2.1.3 小节,如果当前 Realm 的认证和聚合结果都不为 null,就需要对结果进行合并,原本的合并是真正的去合并,这里重写了该方法,就没有去执行合并了:

protected AuthenticationInfo merge(AuthenticationInfo info, AuthenticationInfo aggregate) {

if (aggregate != null && !isEmpty(aggregate.getPrincipals())) {

return aggregate;

}

return info != null ? info : aggregate;

}

这是三个策略中,唯一重写 merge 方法的。

这里的 merge 并没有真正的 merge,而是:

  1. 如果聚合结果不为空,就直接返回聚合结果。

  2. 否则,如果当前认证结果不为空,就返回当前认证结果。

  3. 否则返回空。

可以看到,这里的 merge 其实就是挑选一个认证的 info 返回。如果前面有认证成功的 Realm,后面 Realm 认证成功后返回的 info 是不会被使用的。

2.4.6 小结

好啦,现在小伙伴们可以总结出 FirstSuccessfulStrategy 和 AtLeastOneSuccessfulStrategy 的区别了:

  1. AtLeastOneSuccessfulStrategy:当存在多个 Realm 的时候,即使已经有一个 Realm 认证成功了,后面的 Realm 也还是会去认证,并且如果后面的 Realm 也认证成功了,那么会将多个 Realm 认证成功的结果进行合并。

  2. FirstSuccessfulStrategy:当存在多个 Realm 的时候,默认情况下,即使已经有一个 Realm 认证成功了,后面的 Realm 也还是会去认证,但是如果后面的 Realm 也认证成功了,却并不会使用后面认证成功的 Realm 返回的结果。如果我们希望当一个 Realm 认证成功后,后面的 Realm 就不再认证了,那么可以配置 stopAfterFirstSuccess 属性的值,配置方式如下:

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

写在最后

为了这次面试,也收集了很多的面试题!

以下是部分面试题截图

Java程序员秋招三面蚂蚁金服,我总结了所有面试题,也不过如此

自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-Y4UMOvtO-1711036779701)]
[外链图片转存中…(img-0cgF89HF-1711036779702)]
[外链图片转存中…(img-g9FGoydI-1711036779702)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-8mz7OZ4S-1711036779703)]

写在最后

为了这次面试,也收集了很多的面试题!

以下是部分面试题截图

[外链图片转存中…(img-NUMoNHcg-1711036779703)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值