我尝试使用spring security在websockets上添加身份验证时遇到问题。 此时我已经配置了http以使用当前的安全配置,它工作正常 - 我能够对用户进行身份验证,并返回经过身份验证的主体。但是我想添加一些websocket安全性,一旦我把下面的类应用程序记录下来,但它不想打开任何websockets:
@Configuration
public class WebSocketSecurityConfig extends
AbstractSecurityWebSocketMessageBrokerConfigurer {
protected void configureInbound(
MessageSecurityMetadataSourceRegistry messages) {
messages.nullDestMatcher().permitAll().simpDestMatchers("/app/**")
.authenticated()
.simpSubscribeDestMatchers("/user/*", "/topic/*")
.authenticated();
// TODO
}
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
WebSocketSecurityConfig已正确初始化,因为当我添加permitAll()而不是authenticated()时,它允许我打开websocket。 我确信如果http主体经过身份验证,那么websocket主体也会被验证。我用这个作为参考: http://docs.spring.io/spring-security/site/docs/current/reference/html/websocket.html
以下是控制台中的错误:
org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:127)
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:104)
at org.springframework.web.socket.messaging.StompSubProtocolHandler.handleMessageFromClient(StompSubProtocolHandler.java:266)
at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:309)
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56)
at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:72)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:112)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:42)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:82)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:79)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:393)
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:494)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:289)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:130)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:56)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:203)
at org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:203)
at org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:92)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:609)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:232)
at org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor.preSend(ChannelSecurityInterceptor.java:71)
at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:158)
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:113)
... 24 more
我的配置类:
@Configuration
@EnableWebSocketMessageBroker
@EnableScheduling
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Autowired
HandshakeHandler handshakeManager;
@Autowired
AbstractManagerEventListener eventListenerHandler;
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/queue");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void configureWebSocketTransport(
WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(512 * 1024);
registration.setSendBufferSizeLimit(1024 * 1024);
registration.setSendTimeLimit(40000);
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/channelSocket").setHandshakeHandler(
handshakeManager);
}
@Bean
public HandshakeHandler handshakeManager() throws Exception {
return new HandshakeManager();
}
}
我的HandshakeHandler课程:
public class HandshakeManager extends DefaultHandshakeHandler {
@Override
protected Principal determineUser(ServerHttpRequest request,
WebSocketHandler wsHandler, Map<String, Object> attributes) {
Principal principal = request.getPrincipal();
return new UserPrincipal(principal.getName());
}
}
determineUser(ServerHttpRequest request,
WebSocketHandler wsHandler, Map<String, Object> attributes)
返回与经过身份验证的用户的主体相同的主体。 任何帮助表示赞赏!谢谢!