I have an application where I need two different websocket setups:
Now, in Spring, to disable cross origin checking for websockets one needs to extend AbstractSecurityWebSocketMessageBrokerConfigurer e.g. as follows:
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(final MessageSecurityMetadataSourceRegistry messages) {
messages.anyMessage().authenticated();
}
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
The question is, how can I have it disabled for some websockets and enabled for others?
If you take a look at the method AbstractSecurityWebSocketMessageBrokerConfigurer#configureClientInboundChannel(ChannelRegistration), when you have the sameOriginDisabled set to false, it simply register a CsrfChannelInterceptor:
if (!sameOriginDisabled()) {
registration.setInterceptors(this.context.getBean(CsrfChannelInterceptor.class));
}
And after that, it calls the customizeClientInboundChannel(ChannelRegistration) method.
I can't test now, but I think you can override the method customizeClientInboundChannel(ChannelRegistration) and do the following:
@Override
protected void customizeClientInboundChannel(ChannelRegistration registration) {
registration.addInterceptor(myCustomCsrfChannelInterceptor());
}
private CsrfChannelInterceptor myCustomCsrfChannelInterceptor() {
return new MyCustomCsrfChannelInterceptor();
}
private static class MyCustomCsrfChannelInterceptor {
private MessageMatcher<Object> matcher = //create your MessageMatcher with your rules
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
if (!this.matcher.matches(message)) {
return message;
}
//copy the content from `CsrfChannelInterceptor`
}
}
In summary, what you are doing is creating a custom CsrfChannelInterceptor that will use a custom MessageMatcher with your own rules to check if it should apply to that Message, and the rest is just a copy of the original interceptor.