Spring中的Websocket身份验证和授权
目录
- 一、需要了解的事项
- 二、依赖
- 三、WebSocket 配置
- 3.1 、简单的消息代理
- 3.2 、Spring安全配置
一、需要了解的事项
- http和WebSocket的安全链和安全配置是完全独立的。
- SpringAuthenticationProvider根本不参与 Websocket 身份验证。
- 将要给出的示例中,身份验证不会发生在 HTTP 协商端点上,因为 JavaScript STOMP(websocket)库不会随 HTTP 请求一起发送必要的身份验证标头。
- 一旦在 CONNECT 请求上设置,用户( simpUser) 将被存储在 websocket 会话中,并且以后的消息将不再需要进行身份验证。
二、依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-messaging</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-messaging</artifactId>
</dependency>
三、WebSocket 配置
3.1 、简单的消息代理
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends WebSocketMessageBrokerConfigurer {@Overridepublic void configureMessageBroker(final MessageBrokerRegistry config) {config.enableSimpleBroker("/queue/topic");config.setApplicationDestinationPrefixes("/app");}@Overridepublic void registerStompEndpoints(final StompEndpointRegistry registry) {registry.addEndpoint("stomp"); setAllowedOrigins("*")}
}
3.2 、Spring安全配置
由于 Stomp 协议依赖于第一个 HTTP 请求,因此需要授权对 stomp 握手端点的 HTTP 调用。
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(final HttpSecurity http) throws Exceptionhttp.httpBasic().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers("/stomp").permitAll().anyRequest().denyAll();}
}
然后创建一个负责验证用户身份的服务。
@Component
public class WebSocketAuthenticatorService {public UsernamePasswordAuthenticationToken getAuthenticatedOrFail(final String username, final String password) throws AuthenticationException {if (username == null || username.trim().isEmpty()) {throw new AuthenticationCredentialsNotFoundException("Username was null or empty.");}if (password == null || password.trim().isEmpty()) {throw new AuthenticationCredentialsNotFoundException("Password was null or empty.");}if (fetchUserFromDb(username, password) == null) {throw new BadCredentialsException("Bad credentials for user " + username);}return new UsernamePasswordAuthenticationToken(username,null,Collections.singleton((GrantedAuthority) () -> "USER") // 必须给至少一个角色);}
}
接着需要创建一个拦截器,它将设置“simpUser”标头或在 CONNECT 消息上抛出“AuthenticationException”。
@Component
public class AuthChannelInterceptorAdapter extends ChannelInterceptor {private static final String USERNAME_HEADER = "login";private static final String PASSWORD_HEADER = "passcode";private final WebSocketAuthenticatorService webSocketAuthenticatorService;@Injectpublic AuthChannelInterceptorAdapter(final WebSocketAuthenticatorService webSocketAuthenticatorService) {this.webSocketAuthenticatorService = webSocketAuthenticatorService;}@Overridepublic Message<?> preSend(final Message<?> message, final MessageChannel channel) throws AuthenticationException {final StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);if (StompCommand.CONNECT == accessor.getCommand()) {final String username = accessor.getFirstNativeHeader(USERNAME_HEADER);final String password = accessor.getFirstNativeHeader(PASSWORD_HEADER);final UsernamePasswordAuthenticationToken user = webSocketAuthenticatorService.getAuthenticatedOrFail(username, password);accessor.setUser(user);}return message;}
}
请注意:preSend() 必须返回 UsernamePasswordAuthenticationToken,Spring 安全链中会对此进行测试。如果UsernamePasswordAuthenticationToken构建没有通过GrantedAuthority,则身份验证将失败,因为没有授予权限的构造函数自动设置authenticated = false 这是一个重要的细节,在 spring-security 中没有记录。
最后再创建两个类来分别处理授权和身份验证。
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class WebSocketAuthenticationSecurityConfig extends WebSocketMessageBrokerConfigurer {@Injectprivate AuthChannelInterceptorAdapter authChannelInterceptorAdapter;@Overridepublic void registerStompEndpoints(final StompEndpointRegistry registry) {// 这里不用给任何东西}@Overridepublic void configureClientInboundChannel(final ChannelRegistration registration) {registration.setInterceptors(authChannelInterceptorAdapter);}}
请注意:这@Order是至关重要的,它允许我们的拦截器首先在安全链中注册。
@Configuration
public class WebSocketAuthorizationSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {@Overrideprotected void configureInbound(final MessageSecurityMetadataSourceRegistry messages) {// 添加自己的映射messages.anyMessage().authenticated();}// 这里请自己按需求修改@Overrideprotected boolean sameOriginDisabled() {return true;}
}
之后编写客户端进行连接,我们就可以这样指定客户端进行消息的发送。
@MessageMapping("/greeting")public void greetingReturn(@Payload Object ojd){simpMessagingTemplate.convertAndSendToUser(username,"/topic/greeting",ojd);}
相关文章:
Spring中的Websocket身份验证和授权
目录 一、需要了解的事项二、依赖三、WebSocket 配置3.1 、简单的消息代理3.2 、Spring安全配置 一、需要了解的事项 http和WebSocket的安全链和安全配置是完全独立的。SpringAuthenticationProvider根本不参与 Websocket 身份验证。将要给出的示例中,身份验证不会…...

【果树农药喷洒机器人】Part7:静态PWM变量喷药实验
📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...

C++ 网络编程项目fastDFS分布是文件系统(一)
目录 1.项目架构图 1. 项目架构图 1.1 一些概念 1.2 项目架构图 2. 分布式文件系统 2.1 传统文件系统 2.2 分布式文件系统 3. FastDFS 3.1 fastDFS介绍 3.2 fastDFS安装 3.3 fastDFS配置文件 3.4 fastDFS的启动 4. fastDFS状态检测 4.1 对file_id的解释 4. 2上传…...

PoseiSwap 开启“Poseidon”池,治理体系或将全面开启
PoseiSwap 曾在前不久分别以 IDO、IEO 的方式推出了 POSE 通证,但 PoseiSwap DEX 中并未向除 Zepoch 节点外的角色开放 POSE 资产的交易。而在前不久,PoseiSwap 推出了全新的“Poseidon”池,该池将向所有用户开放,并允许用户自由的…...
【C/C++】重载运算符特性
重载运算符是 C 中的一个重要特性,它允许程序员自定义类类型的运算符行为。重载运算符的使用场景包括: 使类类型的对象能够像内置类型一样进行运算:例如,可以重载加号运算符,使两个对象相加时能够像两个整数相加一样。…...

HTML+JavaScript构建一个将C/C++定义的ANSI字符串转换为MASM32定义的DWUniCode字符串的工具
公文一键排版系统基本完成,准备继续完善SysInfo,增加用户帐户信息,其中涉及到Win32_Account结构,其C定义如下: [Dynamic, Provider("CIMWin32"), UUID("{8502C4CC-5FBB-11D2-AAC1-006008C78BC7}"…...

24届近3年南京信息工程大学自动化考研院校分析
今天给大家带来的是南京信息工程大学控制考研分析 满满干货~还不快快点赞收藏 一、南京信息工程大学 学校简介 南京信息工程大学位于南京江北新区,是一所以大气科学为特色的全国重点大学,由江苏省人民政府、中华人民共和国教育部、中国气…...

【LeetCode】1572.矩阵对角线元素的和
题目 给你一个正方形矩阵 mat,请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例 1: 输入:mat [[1,2,3],[4,5,6],[7,8,9]] 输出:25 解释:对角线的和为&a…...

2023-08-08 Ubuntu 挂载U盘 fdisk -l 、sudo mount /dev/sdb1 /mnt/mydisk
一、基本命令 1、插入U盘,查看U盘是否被系统识别: 打开终端,输入: sudo fdisk -l 查看系统是否识别U盘,如果识别,会显示U盘的相关信息,如果没有识别,则说明系统没有识别U盘。 2…...
make/makefile/cmake/nmake
最近,有没有被make、cmake、makefile... ... 这些东西绕晕了,看看下面的文章,也许就可以理解清楚了。 1. gcc 它是GNU Compiler Collection(就是GNU编译器套件),也可以简单认为是编译器,它可以…...

实用的开源应用全新开源源码Vue3+TS的前后台分离的开发平台源码开源技术社区平台
开源全新开源源码Vue3TS的前后台分离的开发平台源码。创意、新奇、有趣、实用的开源应用、系统、软件、硬件及技术,一个探索、发现、分享、使用与互动交流的开源技术社区平台。致力于打造活力开源社区,共建开源新生态! 功能简介 个人办公&a…...

C++复习笔记——primer第五版
文章目录 一、引用和指针1.引用2.指针2.1利用指针访问对象2.2指针的值或指针所指对象的值的改变 3.赋值和指针4.指向指针的引用 二、String1.初始化String对象的方式2. string对象上的操作3.使用getline读取一整行4.字面值和字符串相加5.使用for循环改变字符串中的字符 三、Vec…...

ElasticSearch:项目实战(2)
ElasticSearch: 项目实战 (1) 需求: 新增文章审核通过后同步数据到es索引库 1、文章服务中添加消息发送方法 在service层文章新增成功后,将数据通过kafka消息同步发送到搜索服务 Autowiredprivate KafkaTemplate<String,String> kafkaTemplate;/…...

Eleastisearch5.2.2利用镜像迁移构建实例后ES非健康状态
正常迁移完成后启动服务,查看ES非健康状态 此时观察ES集群状态:curl -XGET -u elastic:xxx localhost:9200/_cluster/health?pretty 注意到"active_shards_percent_as_number" : 88.8888 该项的值不产生变化;集群状态"status" : “…...

sealos安装k8s
一、前言 1、我前面文章有写过使用 kubeadm 安装的方式,大家可以去参考 (二)k8s集群安装,有一系列的k8s文章说明 2、安装k8s的方式有很多 kubeadmsealoskubespray等等 3、关于sealos来安装 k8s ,也是非常建议大家去…...
经典贪吃蛇游戏 - 用 C 语言实现控制台版
在本篇博客中,我们将一起来实现经典的贪吃蛇游戏,使用 C 语言编写,并在控制台中运行。这个小游戏会让你回忆起童年的经典游戏体验。我们将从游戏的初始化开始,逐步实现游戏的各个功能,包括蛇的移动、食物的生成、得分的…...

安灯Andon系统的应用与优势
安灯系统是一款与硬件相结合,实时了解机台与工位状态,让异常的信息得到快速、高效的解决的系统软件,同时记录每次异常报警的种类、响应时间和处理问题用时,提供改善生产管理和人员考核的数据参考,实现透明、快速的生产…...
2023年的C++基础笔记
C 基本语法 对象 - 对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 - 摇动、叫唤、吃。对象是类的实例。 类 - 类可以定义为描述对象行为/状态的模板/蓝图。 方法 - 从基本上说,一个方法表示一种行为。一个类可以包含多个…...

综合能源系统(6)——综合能源综合评估技术
综合能源系统关键技术与典型案例 何泽家,李德智主编 综合能源系统是多种能源系统非线性耦合的、多时间与空间尺度耦合的“源-网-荷一储”一体化系统,通过能源耦合、多能互补,能够实现能源的高效利用,并提高新能源的利用水平。对…...

华为OD机试真题 Java 实现【寻找相同子串】【2023 B卷 100分】,附详细解题思路
目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷&#…...
微信小程序带参分享、链接功能
分享链接的功能是右上角点...然后复制链接,可以直接点击 #小程序://**商城/p5XqHti******* 这种链接直接从其他地方跳转到小程序 wx.onCopyUrl(() > {return {query: "shareCode" this.shareCode,}; }); query就是参数,直接在onload里…...

第23讲、Odoo18 邮件系统整体架构
目录 Odoo 邮件系统整体架构邮件发送方式邮件模板配置SMTP 邮件服务器配置邮件发送过程开发中常见邮件发送需求常见问题排查提示与最佳实践完整示例:审批通过自动发邮件门户表单自动邮件通知案例邮件队列与异步发送邮件添加附件邮件日志与调试多语言邮件模板邮件安…...
STM32实战: CAN总线数据记录仪设计方案
以下是基于STM32的CAN总线数据记录仪/转发器的设计与实现方案,结合了核心功能和进阶需求: 系统架构 graph TBA[CAN总线] -->|CAN_H/CAN_L| B(STM32 bxCAN)B --> C[数据处理核心]C --> D[SD卡存储<br>FATFS文件系统]C --> E[串口输出…...

Java 大视界 -- 基于 Java 的大数据分布式计算在蛋白质组学数据分析中的加速与优化(255)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...

Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(六):图片上传交互功能
在 《Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(五)》 中,完成了语音交互功能的优化。本文作为该系列教程的第六篇,将聚焦于图片上传功能的开发。通过集成图片上传与预览能力,我们将进一步完善 AI…...

SmolVLA: 让机器人更懂 “看听说做” 的轻量化解决方案
🧭 TL;DR 今天,我们希望向大家介绍一个新的模型: SmolVLA,这是一个轻量级 (450M 参数) 的开源视觉 - 语言 - 动作 (VLA) 模型,专为机器人领域设计,并且可以在消费级硬件上运行。 SmolVLAhttps://hf.co/lerobot/smolvla…...
服务器租用:高防CDN和加速CDN的区别
CDN全称为内容分发网络,其主要的作用原理能够加快网站的数据传输的速度,随着技术的快速发展,CDN也分为高防CDN和加速CDN两种不同的类型,本文将为大家介绍一下高防CDN和加速CDN两者之间的区别有哪些? 高防CDN能够有效抵…...
文件上传漏洞深度解析:检测与绕过技术矩阵
文件上传漏洞深度解析:检测与绕过技术矩阵 引言:无处不在的文件上传风险 在当今的Web应用生态系统中,文件上传功能几乎无处不在。从社交媒体分享图片到企业文档管理系统,用户上传文件已成为现代Web应用的核心功能之一。然而&…...

检测到 #include 错误。请更新 includePath。已为此翻译单元(D:\软件\vscode\test.c)禁用波形曲线
原文链接:【VScodeMinGw】安装配置教程 下载mingw64 打开可以看到bin文件夹下是多个.exe文件,gcc.exe地址在环境配置中要用到 原文链接:VSCode中出现“#include错误,请更新includePath“问题,解决方法 重新VScode后…...

智能制造数字孪生全要素交付一张网:智造中枢,孪生领航,共建智造生态共同体
在制造业转型升级的浪潮中,数字孪生技术正成为推动行业变革的核心引擎。从特斯拉通过数字孪生体实现车辆全生命周期优化,到海尔卡奥斯工业互联网平台赋能千行百业,数字孪生技术已从概念验证走向规模化落地。通过构建覆盖全国的交付网络&#…...