Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用spring security在服务层获取登录用户_Java_Spring_Spring Mvc_Spring Security_Spring Integration - Fatal编程技术网

Java 使用spring security在服务层获取登录用户

Java 使用spring security在服务层获取登录用户,java,spring,spring-mvc,spring-security,spring-integration,Java,Spring,Spring Mvc,Spring Security,Spring Integration,我在服务层中有一个异步方法,它从队列中读取消息。我需要将收到的消息发送给当前登录用户的订户 在我的控制器中,我获取用户作为 (CustomUserDetail)SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 这很好,但服务层中的相同代码会抛出 NullPointerException。可能是由于SecurityContextHolder没有在同一请求-响应流中异步调用,但同时我认为Spring Sec

我在服务层中有一个异步方法,它从队列中读取消息。我需要将收到的消息发送给当前登录用户的订户

在我的控制器中,我获取用户作为

(CustomUserDetail)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
这很好,但服务层中的相同代码会抛出
NullPointerException
。可能是由于
SecurityContextHolder
没有在同一请求-响应流中异步调用,但同时我认为Spring Security会在会话中保留所有用户安全数据。所以它应该可以正常工作

有人能提出解决办法吗。如何在服务层获取已登录用户


我认为一种可能的方法是,当控制器方法将消息推送到队列时,将活动用户添加到会话中,然后从服务层的会话中检索用户。

HTTP会话在那里也不可用

这里的问题只是因为您将调用从一个线程转移到另一个线程

如果你处理,你可以考虑使用你的代码> QuealChans.P/> 否则,您应该将

身份验证
对象与数据一起手动传输到您的服务层


Spring Security可以帮助您,但它没有任何钩子来操作队列…

Spring
SecurityContextHolder
默认模式是
mode\u THREADLOCAL
,这意味着
SecurityContextHolder
仅在同一执行线程中可用

将其更改为
模式\u INHERITABLETHREADLOCAL
,应允许您在所有生成的线程中访问
SecurityContextHolder

SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL)


应该可以解决您的问题。

这只适用于主线程生成的子线程。对于带有@Async注释的方法,它可以很好地工作,但对于队列不起作用,仍然会给出一个NPE。我无法在同级线程之间共享安全上下文(例如,在线程池中)。谢谢你的回答;是否有办法将securitycontextobject添加到线程池或其他对象中,以便每个线程都可以访问它?如果您使用的是spring security 3.2或更高版本,则可以使用Concurncy支持。感谢您的建议,我在消息体中添加了身份验证对象。现在一切正常。我还尝试了在会话中添加用户对象的其他方法,如RequestContextHolder等,但传递带有消息的身份验证对象是最干净的。