与...一起工作Spring Boot 1.2.1.RELEASE
and Spring Websockets
。运行嵌入式时存在部署运行时问题Jetty 9
,我不能伪造用户(java.security.Principal
)当应用程序部署在本地主机以外的其他地方时成功。
我咨询过
- http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-stomp-authentication http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-stomp-authentication
- http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-server-runtime-configuration http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-server-runtime-configuration
下面的配置(我相信)已经“升级”了请求
@Configuration
@EnableWebSocketMessageBroker
@EnableScheduling
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// see http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-stomp-handle-broker-relay
// requires an external broker like AMQP or RabbitMQ
//registry.enableStompBrokerRelay("/queue/", "/topic/");
// XXX This might wind up being the impl we actually deploy; but be aware it has certain constraints
// see http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-stomp-message-flow
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/cards").setHandshakeHandler(new UserHandler()).withSockJS();
}
// cheat; ensure that we have a Principal w/o relying on authentication
class UserHandler extends DefaultHandshakeHandler {
@Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,
Map<String, Object> attributes) {
return new TestPrincipal("bogus");
}
}
这是校长...
public class TestPrincipal implements Principal {
private final String name;
public TestPrincipal(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
}
但这是我收到的例外......
Logger=org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler Type=ERROR Message=Unhandled exception
org.springframework.messaging.simp.annotation.support.MissingSessionUserException: No "user" header in message
at org.springframework.messaging.simp.annotation.support.PrincipalMethodArgumentResolver.resolveArgument(PrincipalMethodArgumentResolver.java:42) ~[spring-messaging-4.1.4.RELEASE.jar!/:4.1.4.RELEASE]
at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) ~[spring-messaging-4.1.4.RELEASE.jar!/:4.1.4.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:127) ~[spring-messaging-4.1.4.RELEASE.jar!/:4.1.4.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:100) ~[spring-messaging-4.1.4.RELEASE.jar!/:4.1.4.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:451) [spring-messaging-4.1.4.RELEASE.jar!/:4.1.4.RELEASE]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:443) [spring-messaging-4.1.4.RELEASE.jar!/:4.1.4.RELEASE]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:82) [spring-messaging-4.1.4.RELEASE.jar!/:4.1.4.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:412) [spring-messaging-4.1.4.RELEASE.jar!/:4.1.4.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:350) [spring-messaging-4.1.4.RELEASE.jar!/:4.1.4.RELEASE]
at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:135) [spring-messaging-4.1.4.RELEASE.jar!/:4.1.4.RELEASE]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_05]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_05]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_05]
这里我还应该考虑什么?
UPDATE
我现在可以在本地主机部署中可靠地重现这一点。
有趣的是,使用STS 3.6.3
在调试模式下,当我在第 91 行设置断点时JettyRequestUpgradeStrategy
public JettyRequestUpgradeStrategy(WebSocketServerFactory factory) {
Assert.notNull(factory, "WebSocketServerFactory must not be null");
this.factory = factory;
this.factory.setCreator(new WebSocketCreator() {
@Override
public Object createWebSocket(ServletUpgradeRequest request, ServletUpgradeResponse response) {
// Cast to avoid infinite recursion
return createWebSocket((UpgradeRequest) request, (UpgradeResponse) response);
}
然后继续到第 41 行设置的另一个断点PrincipalMethodArgumentResolver
@Override
public Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception {
Principal user = SimpMessageHeaderAccessor.getUser(message.getHeaders());
if (user == null) {
throw new MissingSessionUserException(message);
}
return user;
}
the user
is null
。是否存在竞争条件?例如,套接字必须从请求中获取用户是否有一定的时间限制?