每个 STOMP over WebSocket 的消息传递会话都从一个 HTTP 请求开始。这可以是一个升级到 WebSocket 的请求(即 WebSocket 握手),或者在 SockJS 回退的情况下,是一系列的 SockJS HTTP 传输请求。
许多网络应用已经有了 认证和授权,以确保 HTTP 请求的安全。通常情况下,用户通过 Spring Security 使用一些机制进行认证,如登录页面、HTTP 基本认证或其他方式。认证用户的安全上下文被保存在 HTTP 会话中,并与同一基于 cookie 的会话中的后续请求相关联。
因此,对于 WebSocket 握手或 SockJS 的 HTTP 传输请求,通常已经有一个可通过 HttpServletRequest#getUserPrincipal()
访问的认证用户。Spring 会自动将该用户与为其创建的 WebSocket 或 SockJS 会话联系起来,随后通过用户头与通过该会话传输的所有 STOMP 消息联系起来。
简而言之,一个典型的 Web 应用程序除了已经做的安全工作外,不需要做任何其他事情。用户在 HTTP 请求层面通过安全上下文进行认证,该安全上下文通过基于 cookie 的 HTTP 会话(然后与为该用户创建的 WebSocket 或 SockJS 会话相关联)进行维护,并导致在流经应用程序的每个消息上加印用户头。
STOMP 协议在 CONNECT 框架上确实有登录和密码头。这些是最初设计的,也是通过 TCP 的 STOMP 需要的。然而,对于通过WebSocket 的 STOMP,默认情况下,Spring 忽略了 STOMP 协议级别的认证头,并假定用户已经在 HTTP 传输级别进行了认证。我们期望 WebSocket 或 SockJS 会话包含认证的用户。