Authentication

每个通过 WebSocket 进行 STOMP 的消息传递会话都以 HTTP 请求开始。这可能是一个升级到 WebSockets 的请求(即 WebSocket 握手)或者在 SockJS 回退中是一系列 SockJS HTTP 传输请求。

Every STOMP over WebSocket messaging session begins with an HTTP request. That can be a request to upgrade to WebSockets (that is, a WebSocket handshake) or, in the case of SockJS fallbacks, a series of SockJS HTTP transport requests.

许多 Web 应用程序已经启用身份验证和授权以确保 HTTP 请求的安全。一般来说,用户是通过 Spring Security 使用登录页面、HTTP 基本身份验证或其他方式等某种机制进行身份验证的。经身份验证的用户安全上下文会保存在 HTTP 会话中,并与同一基于 Cookie 的会话中的后续请求相关联。

Many web applications already have authentication and authorization in place to secure HTTP requests. Typically, a user is authenticated through Spring Security by using some mechanism such as a login page, HTTP basic authentication, or another way. The security context for the authenticated user is saved in the HTTP session and is associated with subsequent requests in the same cookie-based session.

因此,对于 WebSocket 握手或 SockJS HTTP 传输请求,通常通过 HttpServletRequest#getUserPrincipal() 即可访问已身份验证的用户。Spring 会自动将该用户与为其创建的 WebSocket 或 SockJS 会话以及随后通过用户标头传输到该会话的所有 STOMP 消息相关联。

Therefore, for a WebSocket handshake or for SockJS HTTP transport requests, typically, there is already an authenticated user accessible through HttpServletRequest#getUserPrincipal(). Spring automatically associates that user with a WebSocket or SockJS session created for them and, subsequently, with all STOMP messages transported over that session through a user header.

简而言之,一个典型的 Web 应用程序只需要执行其为安全性而需要执行的操作,而这些操作超出了它已执行的操作。用户会在 HTTP 请求级别通过安全上下文进行身份验证,该安全上下文通过基于 Cookie 的 HTTP 会话维持(然后将其与为该用户创建的 WebSocket 或 SockJS 会话关联),最后会在每个通过应用程序流动的 Message 上压印用户标头。

In short, a typical web application needs to do nothing beyond what it already does for security. The user is authenticated at the HTTP request level with a security context that is maintained through a cookie-based HTTP session (which is then associated with WebSocket or SockJS sessions created for that user) and results in a user header being stamped on every Message flowing through the application.

STOMP 协议在 CONNECT 帧上具有 loginpasscode 标头。它们原本是为 TCP 上的 STOMP 设计的,并且 TCP 上的 STOMP 也需要它们。但是,对于 WebSocket 上的 STOMP,默认情况下,Spring 会忽略 STOMP 协议级别的身份验证标头,并假定用户已经在 HTTP 传输级别进行身份验证。预期 WebSocket 或 SockJS 会话将包含已身份验证的用户。

The STOMP protocol does have login and passcode headers on the CONNECT frame. Those were originally designed for and are needed for STOMP over TCP. However, for STOMP over WebSocket, by default, Spring ignores authentication headers at the STOMP protocol level, and assumes that the user is already authenticated at the HTTP transport level. The expectation is that the WebSocket or SockJS session contain the authenticated user.