【问题标题】:How to authenticate websocket chat by JWT如何通过 JWT 验证 websocket 聊天
【发布时间】:2020-10-09 14:45:32
【问题描述】:

我有一个通过 websockets 进行聊天的功能项目,它已经在运行,现在我需要通过 JWT 实现身份验证。这是请求的流程

  1. 客户端连接到ws://localhost:port/chatting
  2. 客户端订阅自己的收件箱,以便接收来自其他客户端的消息:/user/{userId}/queue/chatting
  3. 客户端可以在 /app/message 中通过在正文中指定向其他用户发送消息: { 'message': msg, 'from': "userId", 'to': "recipientId" },系统会将他们重定向到/user/{recipientId}/queue/chatting

我想确保:

  1. 用户必须进行身份验证才能握手
  2. 用户必须是“userId”才能订阅 /user/"userId"/queue/chatting,这样其他用户就无法访问它。
  3. 用户必须是“userId”才能向正文中from 中具有“userId”的另一个用户发送消息

【问题讨论】:

    标签: spring websocket jwt chat stomp


    【解决方案1】:

    首先添加身份验证可以通过在 WebSecurityConfig 中进行配置来完成,添加自定义 JwtRequestFilter 它将解析您的 JWT 令牌并为该请求设置身份验证上下文。

    一个很好的参考:create-apis-with-jwt-authorization-using-spring-boot

    关于 2 和 3,Springboot 不允许为 STOMP 注册公开动态端点,因此您必须公开 /user/queue/chatting 并且客户端必须直接订阅它。但是,使用convertAndSendToUser(userId, destination, payload),您可以根据 userId 发送消息。此函数在内部调用 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 发送消息。

    【讨论】:

    • 我已经开发了您解决方案的一部分。但是,有一点我不清楚。用户如何订阅用户/队列/聊天,但实际上他正在订阅用户/用户 ID/队列/聊天?我如何在 Spring Boot 中做到这一点?
    • 这是/user 端点的属性。正如我之前所说,当您convertAndSendToUser 时,它会自动将用户名添加到目的地:github.com/spring-projects/spring-framework/blob/…,基本上在订阅您订阅到一个公共目的地时,但是在发送消息时 springboot 会在用户名(或您的情况下的用户 ID)前缀并发送它。
    猜你喜欢
    • 2019-02-10
    • 1970-01-01
    • 2021-08-22
    • 2013-05-08
    • 2016-09-20
    • 2018-03-03
    • 2014-09-22
    • 1970-01-01
    • 2019-06-05
    相关资源
    最近更新 更多