
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 WebSocketSockJS是一个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令牌:
Javaimport 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;@Componentpublic 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令牌:Javaimport 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;@Componentpublic 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拦截器:Javaimport 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@EnableWebSocketMessageBrokerpublic 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;@Componentpublic 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;@Componentpublic 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@EnableWebSocketMessageBrokerpublic class WebSocketconfig extends ABStractSecurityWebSocketMessageBrokerConfigurer { // 省略代码}参考资料:1. JSON Web Token (JWT)官方网站:https://jwt.io/2. SockJS官方网站:https://github.com/sockJS/sockJS-client3. STOMP官方网站:https://stomp.github.io/4. Spring官方网站:https://Spring.io/5. Spring Security官方网站:https://Spring.io/projects/Spring-securityCopyright © 2025 IZhiDa.com All Rights Reserved.
知答 版权所有 粤ICP备2023042255号