Skip to content

Advanced Usage

Sepehr Ghorbanpoor edited this page Aug 28, 2020 · 4 revisions

This page covers everything you should know to change take your configuration to next step!

Intercept handshake

Row by default intercepts handshake for two reasons:

  1. It checks if websocket sub-protocol is for rest over websocket.
  2. It provides ways to authenticate websocket session and map userId to session.

If by any case you need to override all these interceptors you can check the source code of WebsocketConfig.java. You can see which handler is injected for row. Then you can inject that handler in your own websocket config. Just make sure you set the value of row.ws.enable to false in your properties.

Authorization

Row has a default authorization strategy which authorizes all users and assigns a unique incremental id to each user. But row also provides configurable ways for client to send an authorization token to server. You can override the way this token is extracted from header. Also you can override which user information (id and extra object) is assigned to each user.

For starting, create beans that implement TokenExtractor and RowHandshakeAuthHandler with same qualifiers. This overrides the default authorization method.

You can check this demo to see a simple example of extracting a token with header name of X-Auth-Token from handshake and then assign Authentication object to user to be used for Spring Security.

Context

No matter if you have assigned your own user id for user or you let row use its own default strategy, you can always get current user's userId. Row fills a context in requests and you can get that context like this:

String userId = RowContextHolder.getContext().getRowUser().getUserId();

RowSessionRegistry

By injecting this class, you can always get session(s) of a user using userId, which contains userId, extra object filled in handshake, and session for websocket session so you can send messages to. Also don't worry about synchronization issues. This session is already decorated as ConcurrentWebsocketSession. Also note that you can implement your own RowSessionRegistry and inject it as bean, in case you want to keep your user sessions details somewhere else. But remember websocket sesssions are not Serializable.

Spring Security

While this demo is already the good start, to understand more about how to use spring security in your project too, you can think of this strategy:

  1. You first override TokenExtractor to change the way you want to extract users token from handshake.
  2. Then you change RowHandshakeAuthHandler to authorize the user. You can throw AuthenticationFailedException if user's token is invalid. Otherwise, make spring security Authentication (such as UsernamePasswordAuthentication) and return it as extra field in WebsocketUserData. Don't forget to set userId.
  3. Then create authorization filter, and add it before RowInvokerFiler.class. In your filter do these steps:
  • Extract user's id: String userId = RowContextHolder.getContext().getRowUser().getUserId()
  • Get user's session: RowWebsocketSession session = sessionRegistry.getSession(userId)
  • Extract the Authentication object you injected to session earlier: Authentication authentication = (Authentication) session.getExtra()
  • Add the authentication object to spring security context: SecurityContextHolder.getContext().setAuthentication(authentication)

You are all done with spring security!

Clone this wiki locally