当前位置: 首页 > 面试题库 >

ReactiveSecurityContextHolder.getContext()为空,但@AuthenticationPrincipal有效

鲍钊
2023-03-14
问题内容

我一直在Spring Security +
Webflux中使用ReactiveAuthenticationManager。它是经过自定义的,以返回一个实例UsernamePasswordAuthenticationToken,从该实例中我可以确定是调用时应接收的内容ReactiveSecurityContextHolder.getContext().map(ctx -> ctx.getAuthentication()).block()。据我所知,我无法通过两种方式访问​​身份验证上下文:

SecurityContextHolder.getContext().getAuthentication();

要么

ReactiveSecurityContextHolder.getContext().map(ctx -> ctx.getAuthentication()).block()

尝试从控制器或组件访问这些文件将解决null。对于我是否真的要Authentication在自定义管理器中返回实例,我有些疑问,好像我是:

@Override
public Mono<Authentication> authenticate(final Authentication authentication) {
    if (authentication instanceof PreAuthentication) {
        return Mono.just(authentication)
            .publishOn(Schedulers.parallel())
            .switchIfEmpty(Mono.defer(this::throwCredentialError))
            .cast(PreAuthentication.class)
            .flatMap(this::authenticatePayload)
            .publishOn(Schedulers.parallel())
            .onErrorResume(e -> throwCredentialError())
            .map(userDetails -> new AuthenticationToken(userDetails, userDetails.getAuthorities()));
    }

    return Mono.empty();
}

PreAuthentication的实例在哪里扩展AbstractAuthenticationToken``AuthenticationToken``UsernamePasswordAuthenticationToken

有趣的是,尽管ReactiveSecurityContextHolder.getContext().map(ctx -> ctx.getAuthentication()).block()在控制器中不起作用,但我可以@AuthenticationPrincipal在控制器中成功地将带有注释的身份验证主体作为方法参数注入。

这似乎是一个配置问题,但我无法确定在哪里。有人知道为什么我不能返回身份验证吗?


问题答案:

由于您正在使用WebFlux,因此您将使用事件循环来处理请求。您不再像Tomcat那样使用每个请求线程模型。

身份验证按上下文存储。

使用Tomcat ,当请求到达时,Spring将 身份验证 存储在中SecurityContextHolder
SecurityContextHolder使用ThreadLocal变量存储 身份验证 。仅当您尝试从设置了 身份验证
对象ThreadLocal的同一线程中的对象中获取特定 身份验证 对象时,该 身份验证
对象才对您可见。这就是为什么您可以通过静态调用在控制器中获得 身份验证的 原因。ThreadLocalhtml" target="_blank">对象知道返回给您什么,因为它知道您的上下文-
您的线程。

使用WebFlux ,您可以仅使用1个线程来处理所有请求。像这样的静态调用将不再返回预期结果:

SecurityContextHolder.getContext().getAuthentication();

因为不再有使用ThreadLocal对象的方法。为您获取身份验证的唯一方法是在控制器的方法签名中要求身份验证,或者…

从正在ReactiveSecurityContextHolder.getContext()调用的方法返回反应链。

由于您要返回一连串的反应式运算符,因此Spring会对您的链进行订阅以便执行它。当Spring执行此操作时,它将为整个链提供安全上下文。因此,ReactiveSecurityContextHolder.getContext()该链中的每个调用都将返回预期的数据。

您可以在此处阅读有关Mono
/ Flux上下文的更多信息,因为它是Reactor特有的功能。



 类似资料:
  • 试图从控制器或组件访问这些代码将解析为。我有些怀疑我是否真的在自定义管理器中返回了实例,看起来我是: 其中是和扩展的实例 有趣的是,尽管不能在控制器中工作,但我可以将身份验证主体与注释作为方法参数成功地注入控制器中。 这似乎是一个配置问题,但我不知道在哪里。有人知道为什么我不能返回身份验证吗?

  • 问题内容: 我有以下代码: 不,我检查了myLines的内容,这些是正确的。 另外,我得到的印刷品会尽可能频繁地打印“完成”。csv已创建。 但是,如果我手动打开它,它是空的。 这可能是什么原因? 问题答案: 您从不刷新缓冲区或关闭BufferedWriter。 在for循环之后,进行以下调用: 即使有其他资源,在完成后关闭它们也是一个好主意。

  • 我只是想用JS向服务器发送一个请求。但服务器具有空的数组。我可以使用,但在PHP5.6中将不推荐使用它。我可以在数组中发布数据吗? 环境:Chrome、apache2、PHP、AngularJS(我正在使用函数)。 调试映像(很抱歉没有直接附加映像--我没有10信誉)

  • 如上图, 是el-table渲染出来的, img 的src 是由后台提供的: ORIGINALLOGO会为空, 但是却有不同的处理, 一个是图片加载失败的icon, 一个却直接是空的, img 渲染的结果是一样的: 请问各位大佬为什么会有这种情况发生呀, 具体原因是什么呢?

  • 我有一个Spring项目,它使用sping-oaust2和sping-Security使用LDAP身份验证提供程序进行身份验证。 在控制器中,我可以使用< code > @ AuthenticationPrincipal 注释访问当前主体的< code>UserDetails。 然而,当我使用client_credential令牌到达endpoint时,是一个,它是OAuth客户端id。sprin

  • 当我尝试从前端登录时,我遇到了一个错误。我可以注册,但我不能登录。 错误: Java语言lang.NullPointerException:无法调用“com.app.auction.user.user.getName()”,因为“user”在com上为null。应用程序。拍卖使用者UserVM。(UserVM.java:17)~(classes/:na)位于com。应用程序。拍卖授权。AuthCo