Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn more[callout title=Updated Dec 11 2014]Although originally about Spring Security 4.0.0.M2, the blog has been updated to reflect improvements found in Spring Security 4.0 RC1.[/callout]
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.
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");
}
}
[callout title=Direct JSR-356 Support]We have entertained integrating directly with JSR-356. However, at this time it is very difficult since JSR-356 is very low level and currently does not provide the abstractions necessary.[/callout]
This will ensure that:
/user/queue/errors
destination can be accessed by any userROLE_ADMIN
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>
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) {
You can find a complete example, of authorization in the security branch of rwinch/spring-websocket-portfolio.
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.
[callout title=SpringOne 2GX 2014 is around the corner]Book your place at SpringOne in Dallas, TX for Sept 8-11 soon. It's simply the best opportunity to find out first hand all that's going on and to provide direct feedback. From 0 to Spring Security 4.0 session will contain detailed information on how to get started with Spring Security and provide a deep dive into the new features found in Spring Security 4. Of course there plenty of other exciting Spring related talks![/callout]