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等,但传递带有消息的身份验证对象是最干净的。