我的决定是:
我用 STOMP CONNECT frame header
验证而不是 cookie-based authentication
因为移动应用程序没有很好的 Cookie-based authentication
支持。
我用 X-Auth-Token
要获取的标题 Authentication
因为 WebSocket Protocol
不允许javascript更改 HTTP headers
在http握手期间。默认情况下,spring security使用 Cookie-based authentication
spring安全中的身份验证非常简单。
httpsessionconfig.java文件
// see: https://docs.spring.io/spring-session/docs/current/reference/html5/#httpsession-rest
@Configuration
//// Override HttpSession's Filter, in this instance Spring Session is backed by Redis.
//@EnableRedisHttpSession
public class HttpSessionConfig {
// // Default connection configuration, to localhost:6739.
// @Bean
// public LettuceConnectionFactory connectionFactory() {
// return new LettuceConnectionFactory();
// }
// Tell Spring to use HTTP headers, X-Auth-Token.
@Bean
public HttpSessionIdResolver httpSessionIdResolver() {
return HeaderHttpSessionIdResolver.xAuthToken();
}
}
这个 STOMP CONNECT frame header
验证逻辑:
我明白了 String sessionId = ...
从 X-Auth-Token
标题的值。
我明白了 Session session = ...
与 sessionRepository.findById(sessionId)
我明白了 SecurityContextImpl securityContext = ...
与 session.getAttribute("SPRING_SECURITY_CONTEXT")
我明白了 Authentication user = ...
与 securityContext.getAuthentication()
.
最后,我设置了 StompHeaderAccessor accessor
由 accessor.setUser(user)
.
应用程序.yml
server.servlet.session.timeout: 1m
websocketconfig.java文件
@Configuration
// see: https://docs.spring.io/spring-session/docs/current/reference/html5/#websocket-usage
@EnableScheduling
@EnableWebSocketMessageBroker
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class WebSocketConfig extends AbstractSessionWebSocketMessageBrokerConfigurer<Session> {
private final SessionRepository<? extends Session> sessionRepository;
public WebSocketConfig(SessionRepository<? extends Session> sessionRepository) {
this.sessionRepository = sessionRepository;
}
// see: https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#websocket-stomp-authentication-token-based
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new ChannelInterceptor() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String sessionId = accessor.getFirstNativeHeader("X-Auth-Token");
Session session = sessionRepository.findById(sessionId);
if (session != null) {
SecurityContextImpl securityContext = session.getAttribute("SPRING_SECURITY_CONTEXT");
Authentication user = securityContext.getAuthentication();
accessor.setUser(user);
}
}
return message;
}
});
}
@Override
protected void configureStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat");
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/topic", "/queue");
registry.setUserDestinationPrefix("/user");
}
}
我的预期结果是:根据 Spring 会议的正式文件。如果设置 server.servlet.session.timeout: 1m
在 application.yml
我的实际结果是:websocket连接没有终止,用户仍然订阅了 /topic/channel/{channelId}
用户仍然可以向 /app/channel/{channelId}
.
暂无答案!
目前还没有任何答案,快来回答吧!