-
Notifications
You must be signed in to change notification settings - Fork 2
Advanced Usage
This page covers everything you should know to change take your configuration to next step!
Row by default intercepts handshake for two reasons:
- It checks if websocket sub-protocol is for rest over websocket.
- 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.
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.
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();
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.
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:
- You first override
TokenExtractorto change the way you want to extract users token from handshake. - Then you change
RowHandshakeAuthHandlerto authorize the user. You can throwAuthenticationFailedExceptionif user's token is invalid. Otherwise, make spring securityAuthentication(such as UsernamePasswordAuthentication) and return it asextrafield inWebsocketUserData. Don't forget to set userId. - 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
Authenticationobject 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!
Idioglossia Lab - ROW - Spring boot starter