使用 Stomp 在 Spring Boot 中访问 JWT 令牌
Posted
技术标签:
【中文标题】使用 Stomp 在 Spring Boot 中访问 JWT 令牌【英文标题】:Access JWT token in Spring Boot with Stomp 【发布时间】:2022-01-14 16:31:49 【问题描述】:我已经按照this guide 设置了 ng2-stompjs,但是在我的 Spring 引导后端遇到问题,因为我使用的是 JWT 令牌。
首先,由于我的 JWT 安全性,stomp 服务不想连接,所以我将其添加到安全配置中:
安全配置:
http.authorizeRequests().antMatchers("/websockets").permitAll();
WebSocket配置
@Override
public void registerStompEndpoints(StompEndpointRegistry registry)
registry.addEndpoint("/websockets").setAllowedOrigins("*");
我的前端 stomp 配置:
import InjectableRxStompConfig from '@stomp/ng2-stompjs';
export const myRxStompConfig: InjectableRxStompConfig =
// Which server?
brokerURL: 'ws:/localhost:3000/websockets',
// How often to heartbeat?
// Interval in milliseconds, set to 0 to disable
heartbeatIncoming: 0, // Typical value 0 - disabled
heartbeatOutgoing: 20000, // Typical value 20000 - every 20 seconds
// Wait in milliseconds before attempting auto reconnect
// Set to 0 to disable
// Typical value 500 (500 milli seconds)
reconnectDelay: 200,
// Will log diagnostics on console
// It can be quite verbose, not recommended in production
// Skip this key to stop logging to console
debug: (msg: string): void =>
console.log(new Date(), msg);
,
beforeConnect: (stompClient: any): Promise<void> =>
const token = localStorage.getItem('JWT_TOKEN');
return new Promise<void>((resolve, _) =>
stompClient.connectHeaders =
Authorization: 'Bearer ' + token, //also tried x-auth-token
;
resolve();
);
,
;
以及我使用套接字的组件(注意:如果目的地不正确,请忽略,我只是在测试):
ngOnInit(): void
this.rxStompService.watch('/topic/test').subscribe((message: Message) =>
console.log(message.body);
);
public test(): void
this.rxStompService.publish( destination: '/hello' );
有没有办法实际附加令牌?请注意,我使用的是刷新令牌,因此每 10 分钟会生成一个新的访问令牌,并且必须为每个请求使用一个新的访问令牌。
其次,如何在 spring 端点中提取令牌?在其他情况下,我会使用HttpServletRequest
并提取授权标头,但是如何使用套接字执行此操作?我需要这个,因为我需要使用发出请求的人的用户名(一个简单的解决方法是在正文中传递用户名,但如果可能的话,我希望用 JWT 保护它)。
@MessageMapping("/hello")
@SendTo("/topic/test")
public void createGameMP(HttpServletRequest request)
log.info("HI");
log.info(request.getHeader(AUTHORIZATION).substring("Bearer ".length())); // obvious error
【问题讨论】:
【参考方案1】:你可以使用Interceptor拦截websocket请求并在请求中设置token。
-
定义自定义 HandshakeInterceptor
public class MyHandshakeInterceptor implements HandshakeInterceptor
private final static String X_AUTH_TOKEN = "x-auth-token";
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes)
throws Exception
if (request instanceof ServletServerHttpRequest)
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
HttpServletRequest httpServletRequest = servletRequest.getServletRequest();
String token = httpServletRequest.getParameter(X_AUTH_TOKEN);
if (null == token)
httpServletRequest.setParameter(X_AUTH_TOKEN, "xxxxx");//todo token value
return true;
-
配置
@Bean
public HandshakeInterceptor getHandshakeInterceptor()
return new MyHandshakeInterceptor();
@Override
public void registerStompEndpoints(StompEndpointRegistry registry)
registry.addEndpoint("/wse").setAllowedOrigins("*").setInterceptors(myHandshakeInterceptor);
registry.addEndpoint("/wss").setAllowedOrigins("*").setInterceptors(myHandshakeInterceptor);
【讨论】:
似乎无法正常工作。httpServletRequest.getParameter("x-auth-token")
为空。我猜我必须在前端的 stomp 配置中设置 beforeConnect
,但它仍然不起作用。我在原始帖子中编辑了 rxStompConfig 以显示我所做的更改。
@qlabfgerkaSmurf 您好,您可以实现ChannelInterceptor
并覆盖afterSendCompletion()
方法,设置令牌以在StompCommand
CONNECT 时请求。然后就可以在Interceptor中获取token了。以上是关于使用 Stomp 在 Spring Boot 中访问 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring Boot 应用程序中向 STOMP CREATED 消息添加自定义标头?
SockJS over stomp 使用 angular2 和 spring boot
Spring Boot Stomp-Transaction Sockjs: ERROR message=[Bad transaction] Invalid transaction identifier
Spring Boot + Stomp over WS 与嵌入式 Artemis 代理“目标不存在”
带有 stomp js 的 Spring Boot Websocket:我不断收到哎呀!与 http://localhost:8080/ws 的连接丢失