如何通过 JWT 验证 websocket 聊天
How to authenticate websocket chat by JWT
我有一个websockets聊天的功能性项目已经在运行,现在我需要通过JWT实现身份验证。这是请求的流程
- 客户端连接到
ws://localhost:port/chatting
- 客户端订阅自己的收件箱,以便接收来自其他客户端的消息:
/user/{userId}/queue/chatting
- 客户端可以通过在正文中指定向/app/message中的其他用户发送消息:
{ 'message': msg, 'from': "userId", 'to': "recipientId" }
,系统会将他们重定向到 /user/{recipientId}/queue/chatting
我想保护:
- 用户必须进行身份验证才能进行握手
- 用户必须是 "userId" 才能订阅 /user/"userId"/queue/chatting,这样其他用户就可以'无法访问它。
- 用户必须是 "userId" 才能 发送 消息给另一个用户 "userId" in
from
inside body
首先,可以通过在 WebSecurityConfig
中配置相同的方式来添加身份验证,添加一个自定义 JwtRequestFilter
来解析您的 JWT 令牌并为该请求设置身份验证上下文。
同样的一个很好的参考:create-apis-with-jwt-authorization-using-spring-boot。
关于 2 和 3,Springboot 不允许公开 STOMP 注册的动态端点,因此您必须公开 /user/queue/chatting
并且客户端必须直接订阅它。但是,使用执行此操作的 convertAndSendToUser(userId, destination, payload) you can send the message based on the userId. This function internally calls this function this.destinationPrefix(/user) + user(/username) + destination(/queue/chatting)
因此您可以看到变量 user
已作为最终目的地的前缀,您可以传递 userId 而不是 userName.
参考:simpMessagingTemplate.convertAndSendToUser
但请注意,在这种情况下,您必须将此会话的用户名设置为 userId 本身。这可以在您的自定义 JwtRequestFilter
中完成
private void populateSecurityContextHolder(HttpServletRequest request, String userId, List<SimpleGrantedAuthority> grantedAuthorities) {
PreAuthenticatedAuthenticationToken authToken = new PreAuthenticatedAuthenticationToken(
userId, null, grantedAuthorities);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
log.info("Authentication set for userId " + userId);
}
因此,您的服务器可以根据它在消息中收到的 userId 发送消息。
我有一个websockets聊天的功能性项目已经在运行,现在我需要通过JWT实现身份验证。这是请求的流程
- 客户端连接到
ws://localhost:port/chatting
- 客户端订阅自己的收件箱,以便接收来自其他客户端的消息:
/user/{userId}/queue/chatting
- 客户端可以通过在正文中指定向/app/message中的其他用户发送消息:
{ 'message': msg, 'from': "userId", 'to': "recipientId" }
,系统会将他们重定向到/user/{recipientId}/queue/chatting
我想保护:
- 用户必须进行身份验证才能进行握手
- 用户必须是 "userId" 才能订阅 /user/"userId"/queue/chatting,这样其他用户就可以'无法访问它。
- 用户必须是 "userId" 才能 发送 消息给另一个用户 "userId" in
from
inside body
首先,可以通过在 WebSecurityConfig
中配置相同的方式来添加身份验证,添加一个自定义 JwtRequestFilter
来解析您的 JWT 令牌并为该请求设置身份验证上下文。
同样的一个很好的参考:create-apis-with-jwt-authorization-using-spring-boot。
关于 2 和 3,Springboot 不允许公开 STOMP 注册的动态端点,因此您必须公开 /user/queue/chatting
并且客户端必须直接订阅它。但是,使用执行此操作的 convertAndSendToUser(userId, destination, payload) you can send the message based on the userId. This function internally calls this function this.destinationPrefix(/user) + user(/username) + destination(/queue/chatting)
因此您可以看到变量 user
已作为最终目的地的前缀,您可以传递 userId 而不是 userName.
参考:simpMessagingTemplate.convertAndSendToUser
但请注意,在这种情况下,您必须将此会话的用户名设置为 userId 本身。这可以在您的自定义 JwtRequestFilter
private void populateSecurityContextHolder(HttpServletRequest request, String userId, List<SimpleGrantedAuthority> grantedAuthorities) {
PreAuthenticatedAuthenticationToken authToken = new PreAuthenticatedAuthenticationToken(
userId, null, grantedAuthorities);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
log.info("Authentication set for userId " + userId);
}
因此,您的服务器可以根据它在消息中收到的 userId 发送消息。