如何在 websocket 控制器中检索当前登录的用户
Posted
技术标签:
【中文标题】如何在 websocket 控制器中检索当前登录的用户【英文标题】:How to retrieve the current logged in user in a websocket controller 【发布时间】:2022-01-03 18:12:22 【问题描述】:我正在尝试在 websockets 控制器中获取当前经过身份验证的用户。问题是,我无法使用 SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId() 访问用户。 我试图将 Principal 作为方法的参数,但它返回主体 null。 安全配置:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer
@Override
public void registerStompEndpoints(StompEndpointRegistry registry)
registry.addEndpoint("/connect").setAllowedOrigins("*");
@Override
public void configureMessageBroker(MessageBrokerRegistry registry)
registry.enableSimpleBroker("/topic/messages");
registry.setApplicationDestinationPrefixes("/ws");
websocket 控制器:
@Controller
public class MessageController
@Autowired
private Consumer consumer;
@Autowired
private Utils utils;
@Autowired
private PersonService personService;
@Autowired
SimpMessagingTemplate simpMessagingTemplate;
String destination = "/topic/messages";
ExecutorService executorService =
Executors.newFixedThreadPool(1);
Future<?> submittedTask;
@MessageMapping("/start")
public void startTask(Principal principal)
// Here, I would like to get the logged in user
// If I use principal like this: principal.getName() => NullPointerException
if ( submittedTask != null )
simpMessagingTemplate.convertAndSend(destination,
"Task already started");
return;
simpMessagingTemplate.convertAndSendToUser(sha.getUser().getName(), destination,
"Started task");
submittedTask = executorService.submit(() ->
while(true)
simpMessagingTemplate.convertAndSend(destination,
// "The calculated value " + val + " is equal to : " + max);
);
如何获取经过身份验证的用户?我需要它来检查何时启动 Web 套接字的任务
【问题讨论】:
不要将代码发布为图像,而是作为代码发布,请添加您的完整控制器和安全配置。 @M.Deinum 修改了问题 你的 websocket 安全配置在哪里? 您的处理程序也错了,您将状态存储在控制器(submittedTask
)上,这是错误的。
嗯以上。它被称为 WebSocketConfig
【参考方案1】:
尝试实现ChannelInterceptor,需要在Config文件中注册(实现WebSocketMessageBrokerConfigurer的类)
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer
private final ChannelInterceptor serverPushInBoundInterceptor;
@Autowired
public WebSocketConfig(@Qualifier("serverPushInBoundInterceptor") ChannelInterceptor serverPushInBoundInterceptor)
this.serverPushInBoundInterceptor = serverPushInBoundInterceptor;
....
@Override
public void configureClientInboundChannel(ChannelRegistration registration)
registration.interceptors(serverPushInBoundInterceptor);
@Component("serverPushInBoundInterceptor")
public class ServerPushInBoundInterceptor implements ChannelInterceptor
private static final Logger log = LoggerFactory.getLogger(ServerPushInBoundInterceptor.class);
@Override
@SuppressWarnings("NullableProblems")
public Message<?> postReceive(Message<?> message, MessageChannel channel)
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(Objects.requireNonNull(accessor).getCommand()))
List<String> authorization = accessor.getNativeHeader("Authorization");
if (authorization != null && !authorization.isEmpty())
String auth = authorization.get(0).split(" ")[1];
System.out.println(auth);
try
// find Principal
Principal principal = ...
accessor.setUser(new UsernamePasswordAuthenticationToken(principal, principal.getCredentials(), principal.getAuthorities()));
catch (Exception exc)
log.error("preSend", exc);
return message;
【讨论】:
以上是关于如何在 websocket 控制器中检索当前登录的用户的主要内容,如果未能解决你的问题,请参考以下文章
Cakephp 3 - 如何在验证过程中检索“表”类中的当前登录用户?