JSON Web Token (JWT) 与基于 Spring 的 SockJS STOMP Web Socket

springJS

1个回答

写回答

b46688908

2025-07-06 22:05

+ 关注

JS
JS

使用JSON Web Token (JWT)和基于Spring的SockJS/STOMP WebSocket来实现安全的实时通信

引言:

在现代Web应用程序中,实时通信变得越来越重要。为了实现实时通信,WebSocket被广泛使用。而为了保证通信的安全性,JSON Web Token (JWT)是一种常用的身份验证和授权机制。本文将介绍如何使用JWT和基于Spring的SockJS/STOMP WebSocket来实现安全的实时通信。

I. 什么是JSON Web Token (JWT)

JSON Web Token (JWT)是一种用于身份验证和授权的开放标准(RFC 7519)。它由三部分组成:头部(header)、载荷(payload)和签名(signature)。头部包含了加密算法和令牌类型等信息,载荷包含了要传输的数据,签名用于验证令牌的真实性。

II. 什么是SockJS/STOMP WebSocket

SockJS是一个JavaScript库,它提供了对WebSocket的抽象,使得在不支持WebSocket的浏览器上也可以使用类似WebSocket的实时通信功能。STOMP(Simple Text Oriented Messaging Protocol)是一种在Web应用程序之间进行异步消息传输的协议。Spring框架提供了对SockJS和STOMP的支持,使得在Spring应用程序中可以方便地使用WebSocket进行实时通信。

III. 使用JWT保护WebSocket通信

为了保护WebSocket通信,我们可以使用JWT进行身份验证和授权。下面是一个使用Spring Security和JWT的示例代码:

首先,添加JWT依赖到项目的pom.XML文件中:

<dependency>

<groupId>io.JSonwebtoken</groupId>

<artifactId>jjwt</artifactId>

<version>0.9.1</version>

</dependency>

然后,创建一个JWT工具类来生成和验证JWT令牌:

Java

import io.JSonwebtoken.ClAIms;

import io.JSonwebtoken.Jwts;

import io.JSonwebtoken.SignatureALGorithm;

import org.Springframework.beans.factory.annotation.Value;

import org.Springframework.stereotype.Component;

import Java.util.Date;

import Java.util.HashMap;

import Java.util.Map;

@Component

public class JwtUtils {

@Value("${jwt.secret}")

private String secret;

@Value("${jwt.expiration}")

private int expiration;

public String generateToken(String username) {

Date now = new Date();

Date expiryDate = new Date(now.getTime() + expiration * 1000);

Map<String, Object> clAIms = new HashMap<>();

clAIms.put("sub", username);

return Jwts.builder()

.setclAIms(clAIms)

.setIssuedAt(now)

.setExpiration(expiryDate)

.signWith(SignatureALGorithm.HS512, secret)

.compact();

}

public String getUsernameFromToken(String token) {

ClAIms clAIms = Jwts.parser()

.setSigningKey(secret)

.parseClAImsJws(token)

.getBody();

return clAIms.getSubject();

}

public boolean validateToken(String token) {

try {

Jwts.parser().setSigningKey(secret).parseClAImsJws(token);

return true;

} catch (Exception e) {

return false;

}

}

}

接下来,创建一个WebSocket拦截器来验证JWT令牌:

Java

import org.Springframework.beans.factory.annotation.Autowired;

import org.Springframework.http.HttpHeaders;

import org.Springframework.messaging.Message;

import org.Springframework.messaging.MessageChannel;

import org.Springframework.messaging.simp.stomp.StompCommand;

import org.Springframework.messaging.simp.stomp.StompHeaderAccessor;

import org.Springframework.messaging.support.ChannelInterceptor;

import org.Springframework.messaging.support.MessageHeaderAccessor;

import org.Springframework.security.core.Authentication;

import org.Springframework.security.core.context.SecurityContextHolder;

import org.Springframework.stereotype.Component;

@Component

public class JwtWebSocketInterceptor implements ChannelInterceptor {

@Autowired

private JwtUtils jwtUtils;

@Override

public Message<?> preSend(Message<?> message, MessageChannel channel) {

StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

if (StompCommand.CONNECT.equals(accessor.getcommand())) {

String token = accessor.getFirstNativeHeader(HttpHeaders.AUTHORIZATION);

if (token != null && token.startsWith("Bearer ")) {

token = token.substring(7);

if (jwtUtils.validateToken(token)) {

String username = jwtUtils.getUsernameFromToken(token);

Authentication authentication = new JwtAuthenticationToken(username);

SecurityContextHolder.getcontext().setAuthentication(authentication);

accessor.setUser(authentication);

}

}

}

return message;

}

}

最后,配置Spring Security以使用JWT和WebSocket拦截器:

Java

import org.Springframework.beans.factory.annotation.Autowired;

import org.Springframework.context.annotation.Configuration;

import org.Springframework.messaging.simp.config.MessageBrokerRegistry;

import org.Springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry;

import org.Springframework.security.config.annotation.web.socket.ABStractSecurityWebSocketMessageBrokerConfigurer;

import org.Springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;

import org.Springframework.web.socket.config.annotation.StompEndpointRegistry;

@Configuration

@EnableWebSocketMessageBroker

public class WebSocketconfig extends ABStractSecurityWebSocketMessageBrokerConfigurer {

@Autowired

private JwtWebSocketInterceptor jwtWebSocketInterceptor;

@Override

protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {

messages.simpDestMatchers("/topic/**").authenticated();

}

@Override

protected void configureStompEndpoints(StompEndpointRegistry registry) {

registry.addEndpoint("/websocket")

.setAllowedOrigins("*")

.withSockJS();

}

@Override

public void configureMessageBroker(MessageBrokerRegistry registry) {

registry.setApplicationDestinationPrefixes("/app")

.enableSimpleBroker("/topic");

}

@Override

protected boolean sameOriginDisabled() {

return true;

}

@Override

protected boolean isCsrfProtectionEnabled() {

return false;

}

@Override

protected void customizeClientInboundChannel(ChannelRegistration registration) {

registration.interceptors(jwtWebSocketInterceptor);

}

}

IV.

通过使用JSON Web Token (JWT)和基于Spring的SockJS/STOMP WebSocket,我们可以实现安全的实时通信。JWT用于身份验证和授权,而SockJS/STOMP WebSocket提供了实时通信的功能。通过将JWT令牌和WebSocket拦截器结合我们可以保护WebSocket通信的安全性。

使用JSON Web Token (JWT)保护WebSocket通信的示例代码:

Java

// JWT工具类

import io.JSonwebtoken.ClAIms;

import io.JSonwebtoken.Jwts;

import io.JSonwebtoken.SignatureALGorithm;

import org.Springframework.beans.factory.annotation.Value;

import org.Springframework.stereotype.Component;

import Java.util.Date;

import Java.util.HashMap;

import Java.util.Map;

@Component

public class JwtUtils {

// 省略代码

}

// WebSocket拦截器

import org.Springframework.beans.factory.annotation.Autowired;

import org.Springframework.http.HttpHeaders;

import org.Springframework.messaging.Message;

import org.Springframework.messaging.MessageChannel;

import org.Springframework.messaging.simp.stomp.StompCommand;

import org.Springframework.messaging.simp.stomp.StompHeaderAccessor;

import org.Springframework.messaging.support.ChannelInterceptor;

import org.Springframework.messaging.support.MessageHeaderAccessor;

import org.Springframework.security.core.Authentication;

import org.Springframework.security.core.context.SecurityContextHolder;

import org.Springframework.stereotype.Component;

@Component

public class JwtWebSocketInterceptor implements ChannelInterceptor {

// 省略代码

}

// WebSocket配置

import org.Springframework.beans.factory.annotation.Autowired;

import org.Springframework.context.annotation.Configuration;

import org.Springframework.messaging.simp.config.MessageBrokerRegistry;

import org.Springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry;

import org.Springframework.security.config.annotation.web.socket.ABStractSecurityWebSocketMessageBrokerConfigurer;

import org.Springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;

import org.Springframework.web.socket.config.annotation.StompEndpointRegistry;

@Configuration

@EnableWebSocketMessageBroker

public class WebSocketconfig extends ABStractSecurityWebSocketMessageBrokerConfigurer {

// 省略代码

}

参考资料:

1. JSON Web Token (JWT)官方网站:https://jwt.io/

2. SockJS官方网站:https://github.com/sockJS/sockJS-client

3. STOMP官方网站:https://stomp.github.io/

4. Spring官方网站:https://Spring.io/

5. Spring Security官方网站:https://Spring.io/projects/Spring-security

举报有用(4)分享收藏

Copyright © 2025 IZhiDa.com All Rights Reserved.

知答 版权所有 粤ICP备2023042255号