一、认证架构设计

1.1 WebSocket安全认证流程

客户端服务端HTTP握手请求(携带Token)认证拦截器校验Token101 Switching ProtocolsWebSocket通信401 Unauthorizedalt[认证成功][认证失败]客户端服务端

1.2 安全组件矩阵

组件职责关键技术点
HandshakeInterceptor握手前认证Token解析/校验
ChannelInterceptor消息级鉴权@PreAuthorize
SimpUserRegistry用户会话管理Principal关联
SecurityContext安全上下文线程局部变量

二、生产级认证实现

2.1 JWT认证拦截器

public class JwtHandshakeInterceptor implements HandshakeInterceptor {private final JwtDecoder jwtDecoder;@Overridepublic boolean beforeHandshake(ServerHttpRequest request,ServerHttpResponse response,WebSocketHandler wsHandler,Map<String, Object> attributes) throws Exception {String token = extractToken(request);if (token == null) {response.setStatusCode(HttpStatus.UNAUTHORIZED);return false;}try {Jwt jwt = jwtDecoder.decode(token);attributes.put("jwt", jwt);return true;} catch (JwtException e) {response.setStatusCode(HttpStatus.FORBIDDEN);return false;}}private String extractToken(ServerHttpRequest request) {// 从Header/QueryParam/Cookie中提取TokenList<String> headers = request.getHeaders().get("Authorization");if (headers != null && !headers.isEmpty()) {String header = headers.get(0);if (header.startsWith("Bearer ")) {return header.substring(7);}}return null;}@Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,WebSocketHandler wsHandler, Exception exception) {// 握手后处理逻辑}
}

2.2 消息级权限控制

@Configuration
@EnableWebSocketSecurity
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {@Overrideprotected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {messages.simpDestMatchers("/app/device/**").hasRole("DEVICE").simpSubscribeDestMatchers("/topic/admin/**").hasRole("ADMIN").simpSubscribeDestMatchers("/user/queue/**").authenticated().anyMessage().denyAll();}@Overrideprotected boolean sameOriginDisabled() {return true; // 禁用CSRF保护(根据需求配置)}@Beanpublic ChannelInterceptor authorizationChannelInterceptor() {return new ChannelInterceptor() {@Overridepublic Message<?> preSend(Message<?> message, MessageChannel channel) {StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);if (StompCommand.CONNECT.equals(accessor.getCommand())) {Authentication auth = (Authentication) accessor.getHeader("simpUser");if (auth == null || !auth.isAuthenticated()) {throw new AuthenticationCredentialsNotFoundException("未认证");}}return message;}};}
}

三、高级安全特性

3.1 双因素认证集成

public class TwoFactorAuthInterceptor implements ChannelInterceptor {@Overridepublic Message<?> preSend(Message<?> message, MessageChannel channel) {StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);if (StompCommand.SUBSCRIBE.equals(accessor.getCommand())) {Principal principal = accessor.getUser();String sessionId = accessor.getSessionId();if (isSensitiveDestination(accessor.getDestination()) &&!twoFactorService.isVerified(principal.getName(), sessionId)) {throw new TwoFactorRequiredException("需要二次认证");}}return message;}private boolean isSensitiveDestination(String destination) {return destination != null &&(destination.startsWith("/topic/finance") ||destination.startsWith("/app/admin"));}
}

3.2 速率限制控制

@Bean
public ChannelInterceptor rateLimitingInterceptor() {return new ChannelInterceptor() {private final RateLimiter limiter = RateLimiter.create(100); // 100条/秒@Overridepublic Message<?> preSend(Message<?> message, MessageChannel channel) {if (!limiter.tryAcquire()) {throw new RateLimitExceededException("消息发送频率过高");}return message;}};
}

四、集群环境方案

4.1 分布式会话管理

@Configuration
@EnableRedisHttpSession
public class SessionConfig {@Beanpublic RedisMessageListenerContainer redisContainer(RedisConnectionFactory factory,SessionExpiredListener listener) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(factory);container.addMessageListener(listener,new PatternTopic("__keyevent@*__:expired"));return container;}@Componentpublic static class SessionExpiredListener implements MessageListener {@Autowiredprivate SimpUserRegistry userRegistry;@Overridepublic void onMessage(Message message, byte[] pattern) {String key = new String(message.getBody());if (key.startsWith("spring:session:sessions:")) {String sessionId = key.substring(25);userRegistry.users().stream().filter(user -> user.getSession(sessionId) != null).findFirst().ifPresent(user -> {SimpUser simpUser = userRegistry.getUser(user.getName());simpUser.getSession(sessionId).close(CloseStatus.SESSION_NOT_RELIABLE);});}}}
}

4.2 跨节点消息审计

@Configuration
public class AuditConfig {@Beanpublic MessageChannel auditChannel() {return new ExecutorSubscribableChannel(taskExecutor());}@Beanpublic ThreadPoolTaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(1000);return executor;}@Bean@ServiceActivator(inputChannel = "auditChannel")public MessageHandler auditHandler() {return message -> {StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);String user = Optional.ofNullable(accessor.getUser()).map(Principal::getName).orElse("anonymous");auditService.log(user,accessor.getSessionId(),accessor.getCommand().name(),accessor.getDestination(),Instant.now());};}
}

五、监控与运维

5.1 健康检查端点

@RestController
@RequestMapping("/actuator/websocket")
public class WebSocketMetricsEndpoint {@Autowiredprivate SimpUserRegistry userRegistry;@GetMapping("/connections")public Map<String, Object> connectionMetrics() {Map<String, Object> metrics = new LinkedHashMap<>();metrics.put("activeConnections", userRegistry.getUserCount());metrics.put("activeSessions", userRegistry.users().stream().mapToInt(u -> u.getSessions().size()).sum());return metrics;}@GetMapping("/users")public Collection<SimpUser> activeUsers() {return userRegistry.users();}
}

5.2 异常处理策略

@ControllerAdvice
public class WebSocketExceptionHandler {@MessageExceptionHandler@SendToUser("/queue/errors")public ErrorResponse handleException(Exception ex) {ErrorResponse response = new ErrorResponse();response.setTimestamp(Instant.now());if (ex instanceof AuthenticationException) {response.setCode("AUTH_ERROR");response.setMessage("认证失败");} else if (ex instanceof AccessDeniedException) {response.setCode("ACCESS_DENIED");response.setMessage("权限不足");} else {response.setCode("INTERNAL_ERROR");response.setMessage("服务器内部错误");}return response;}@Datapublic static class ErrorResponse {private String code;private String message;private Instant timestamp;}
}

六、前端安全集成

6.1 Token刷新机制

function connectWebSocket() {const socket = new SockJS('/ws');const stompClient = Stomp.over(socket);const headers = {'Authorization': `Bearer ${getAccessToken()}`};stompClient.connect(headers, () => {// 连接成功处理}, (error) => {if (error.headers?.message === 'TOKEN_EXPIRED') {refreshToken().then(newToken => {headers.Authorization = `Bearer ${newToken}`;connectWebSocket(); // 重连});}});
}

6.2 安全断开处理

function setupWebSocket() {let reconnectAttempts = 0;const maxReconnectAttempts = 3;function connect() {stompClient.connect(headers, frame => {reconnectAttempts = 0;// 心跳检测const heartbeatInterval = setInterval(() => {if (!stompClient.connected) {clearInterval(heartbeatInterval);return;}stompClient.send("/app/heartbeat");}, 30000);stompClient.onclose = () => {clearInterval(heartbeatInterval);if (reconnectAttempts < maxReconnectAttempts) {setTimeout(connect, 1000 * Math.pow(2, reconnectAttempts));reconnectAttempts++;}};});}window.addEventListener('beforeunload', () => {if (stompClient.connected) {stompClient.disconnect(() => {}, {});}});
}

通过以上方案,可以构建出企业级安全的WebSocket通信系统。建议在实际部署时:

  1. 根据业务需求调整认证粒度
  2. 实施完善的监控告警机制
  3. 定期进行安全审计
  4. 建立完整的证书管理体系
  5. 制定详细的应急响应预案

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/92806.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/92806.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/92806.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

复现论文《多无人机协同任务分配算法设计与实现》

1. 论文标题 多无人机协同任务分配算法设计与实现 The Design and Implementation of Multi-UAVs Cooperative Task Assignment Algorithm 2. 内容概括 该论文针对异构多无人机协同执行多目标多类型任务时的分配问题展开研究。首先提出“两阶段”任务分配结构:第一阶段通过…

MCU-基于TC397的启动流程

TC397的启动流程(Start Sequence) 整体启动流程包括固件启动(Boot Firmware)和 Bootloader 和软件启动(Application start-up software)三个阶段。 1. Boot Firmware:是芯片上电后最开始执行的代码,代码由英飞凌供应商固化在BootRom中的,不可编程,没办法对BootRom中的…

单片机毕业设计模板|毕设答辩|毕业设计项目|毕设设计|单片机物联网毕业设计|基于STM32单片机的纱管图像识别系统设计

毕业设计题目&#xff1a;基于STM32单片机的纱管图像识别系统设计1. 需求分析目标用户&#xff1a;纺织行业&#xff0c;自动化生产线&#xff0c;质量检测等。核心功能&#xff1a;实时识别和检测纱管的外观缺陷&#xff08;如破损、色差等&#xff09;。提供数据记录和报告功…

谷歌DeepMind发布Genie 3:通用型世界模型,可生成前所未有多样化的交互式虚拟环境

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

202506 电子学会青少年等级考试机器人二级理论综合真题

更多内容和历年真题请查看网站&#xff1a;【试卷中心 -----> 电子学会 ----> 机器人技术 ----> 二级】 网站链接 青少年软件编程历年真题模拟题实时更新 2025年6月 青少年等级考试机器人理论真题二级 第 1 题 如图&#xff0c;这是中国古代发明的指南车模型&am…

【YOLO11改进 - C3k2融合】C3k2融合EBlock(Encoder Block):低光增强编码器块,利用傅里叶信息增强图像的低光条件

YOLOv11目标检测创新改进与实战案例专栏 文章目录&#xff1a; YOLOv11创新改进系列及项目实战目录 包含卷积&#xff0c;主干 注意力&#xff0c;检测头等创新机制 以及 各种目标检测分割项目实战案例 专栏链接: YOLOv11目标检测创新改进与实战案例 文章目录YOLOv11目标检测创…

MACBOOK M1安装达梦8数据库

前提已安装好了docker 然后通过docker-compose安装 version: 2.1 services:DM8:image: qinchz/dm8-arm64:8.1.8.128container_name: dm8ports:- "52330:5236"mem_limit: 2gmemswap_limit: 2genvironment:- TZAsia/Shanghai- LANGen_US.UTF-8volumes:- /Users/a1/dock…

2013年考研数学(二)真题

一、选择题(1)考点&#xff1a;低阶无穷小定义、高阶无穷小定义、同阶无穷小定义、等阶无穷小定义、移项变形/极限存在并且分母→0时则分子也→0方法一&#xff1a;方法二&#xff1a;(2)考点&#xff1a;说不清楚的思路/凑导数定义式、洛必达法则、隐函数求导方法一&#xff1…

WinForm 复合控件(用户控件):创建与使用指南

目录 添加流程示意图 复合控件的核心价值 与自定义控件的区别 创建步骤 建好的示例控件 ​使用方法&#xff08;代码示例&#xff09; 设计原则 添加流程示意图 点击添加 添加成功 每更新一次复合控件的内容&#xff0c;就需要生成一次 ↓ 添加好复合控件后点这里更新一…

随机向量正交投影定理(Orthogonal Projection Theorem, OPT)_学习笔记

前言 随机向量正交投影定理&#xff08;Orthogonal Projection Theorem, OPT&#xff09; 是理解和推导卡尔曼了滤波&#xff08;Kalman Filtrering, KF&#xff09; 重要理论工具&#xff0c;简化卡尔曼最优滤波方程推导过程并提供数学严密性。本文介绍该定理内容及证明过程&a…

11-netty基础-手写rpc-支持多序列化协议-03

netty系列文章&#xff1a; 01-netty基础-socket02-netty基础-java四种IO模型03-netty基础-多路复用select、poll、epoll04-netty基础-Reactor三种模型05-netty基础-ByteBuf数据结构06-netty基础-编码解码07-netty基础-自定义编解码器08-netty基础-自定义序列化和反序列化09-n…

艾体宝产品 | 从“被看见”到“被信任”:GWI 协助洞察消费者,重构品牌认知

简介&#xff1a;本文介绍了基于消费者洞察构建品牌认知策略的核心方法。通过深度理解受众&#xff0c;GWI Spark 快速获取真实洞察&#xff0c;指导信息与渠道选择。GWI 帮助追踪情感与认知效果&#xff0c;避免无效曝光陷阱&#xff0c;最终帮助品牌实现从“被看见”到“被信…

Redis高级

目录 一、Redis主从 1. 主从集群结构 2. 主从同步原理 2.1 全量同步 2.2 增量同步 3. 主从同步优化 4. 总结 二、Redis哨兵 1. 哨兵工作原理 1.1 哨兵作用 1.2 状态监控 1.3 选举新的master节点 2. 总结 三、Redis分片集群 1. 散列插槽 2. 故障转移 四、Redis…

正点原子esp32s3探测土壤湿度

开发板使用&#xff1a;正点原子ATK_DNESP32S3 V1.3 IDE: VSCODE PLATFORMIO 土壤湿度检测传感器模块如下图&#xff1a; 引脚&#xff1a; 传感器VCC --> ESP32[3.3V] 传感器GND --> ESP32[GND] 传感器A0 --> ESP32[GPIO20] 代码如下&#xff1a; #include <…

一篇文章解决 Win10 同时部署多个版本的Tomcat

文章目录所用到的文件夹Tomcat服务端口修改Tomcat参数修改环境变量配置验证环境是否配置成功可能遇到的问题问题一&#xff1a;startup.bat闪退问题二&#xff1a;startup.bat成功启动&#xff0c;但仍打不开服务器总结最近在学习JavaWeb的时候&#xff0c;想安装新版本的Tomca…

CentOS7安装和使用Workbench

文章目录CentOS7安装和使用Workbench一、前言1.简介2.环境二、正文1.更换镜像源2.安装依赖包3.下载4.安装5.打开workbench6.使用记录1&#xff09;连接数据库2&#xff09;创建数据库3&#xff09;导入数据3&#xff09;导出数据4&#xff09;运行SQL脚本5&#xff09;打开SQL脚…

SpringBoot查询方式全解析

文章目录一、简介二、常用注解分类1、请求映射类&#xff08;处理 URL 与 HTTP 方法的绑定&#xff09;2、参数绑定类&#xff08;从请求中获取数据并绑定到方法参数&#xff09;3、控制器与增强类&#xff08;标识控制器及全局增强&#xff09;4、异常与响应处理类&#xff08…

Linux操作系统从入门到实战(十五)详细讲解Linux调试器 gdb/cgdb使用

Linux操作系统从入门到实战&#xff08;十五&#xff09;详细讲解Linux调试器 gdb/cgdb使用前言一、gdb/cgdb是什么&#xff1f;1. 程序的两种发布模式&#xff08;debug 和 release&#xff09;二、gdb/cgdb如何启动&#xff1f;1. 准备工作2. 启动 gdb/cgdb 调试器2.1 启动 g…

基于UDP的代理协议的Tuic怎么样?

Tuic&#xff08;全称“TUIClient”&#xff09;是一款基于UDP协议的轻量代理工具&#xff0c;主打低延迟与高实时性&#xff0c;专为解决传统TCP代理在实时场景中的性能瓶颈而生。其核心设计围绕“UDP优先”展开&#xff0c;通过简化握手流程、优化加密效率&#xff0c;在保持…

缓存投毒进阶 -- justctf 2025 Busy Traffic

题目核心逻辑如下 let browser; // 全局浏览器实例// 访问指定 URL 的异步函数 const visit async (url) > {try {// 如果已有浏览器实例&#xff0c;先关闭并等待 2 秒if (browser) {await browser.close();await sleep(2000);console.log("Terminated ongoing job.&…