Preview Spring Security WebSocket Support
Introduction
Previously, an application could use Spring Security to perform authentication in a WebSocket application. This worked because the Principal
of an HttpServletRequest
will be propagated to the WebSocket Session.
The problem is that authorization was limited to handshake. This means that once the connection was made, there was no way to provide any granularity to authorization of the WebSocket application.
Using Spring Security’s Messaging Support
Spring Security 4.0.0.RC2 has introduced authorization support for WebSockets through the Spring Messaging abstraction. To provide authorization, simply extend the AbstractSecurityWebSocketMessageBrokerConfigurer
and configure the MessageSecurityMetadataSourceRegistry
. For example:
public class WebSocketSecurityConfig extends
AbstractSecurityWebSocketMessageBrokerConfigurer {
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
. simpDestMatchers("/user/queue/errors").permitAll()
. simpDestMatchers("/**").hasRole("ADMIN");
}
}
This will ensure that:
- The
/user/queue/errors
destination can be accessed by any user - Any other Message containing a destination header can only be accessed by users with the role of
ROLE_ADMIN
XML Namespace Support
Similarly we could have defined the above configuration using the Spring Security XML Namespace Support. The equivalent configuration is:
<websocket-message-broker>
<!-- pattern matches on the destination header -->
<intercept-message pattern="/user/queue/errors" access="permitAll" />
<intercept-message pattern="/**" access="hasRole('ROLE_ADMIN')" />
</websocket-message-broker>
Method Security and WebSockets
We can also use method security with WebSockets. For example, the following method can only be invoked by a user with the role ROLE_ADMIN
:
@PreAuthorize("hasRole('ROLE_ADMIN')")
@MessageMapping("/trade")
public void executeTrade(Trade trade, Principal principal) {
Sample Application
You can find a complete example, of authorization in the security branch of rwinch/spring-websocket-portfolio.
What Next?
While this resolves our authorization problems, we still are missing a good mechanism to keep our HttpSession
alive when sending messages over WebSockets. In the next post, I will discuss in more detail what these problems are and how Spring Session can alleviate these problems.