微服务OAuth 2.1扩展额外信息到JWT并解析(Spring Security 6)
文章目录
- 一、简介
- 二、重写UserDetailsService
- 三、Controller解析JWT获取用户信息
- 四、后记
一、简介
Version | |
---|---|
Java | 17 |
SpringCloud | 2023.0.0 |
SpringBoot | 3.2.1 |
Spring Authorization Server | 1.2.1 |
Spring Security | 6.2.1 |
mysql | 8.2.0 |
Spring Authorization Server
使用JWT
时,前两部分默认格式如下
{"kid": "33bd1cad-62a6-4415-89a6-c2c816f3d3b1","alg": "RS256"
}
{"sub": "XcWebApp","aud": "XcWebApp","nbf": 1707373072,"iss": "http://localhost:63070/auth","exp": 1707380272,"iat": 1707373072,"jti": "62e885c5-6b3f-49a2-aa10-b2e872a52b33"
}
现在我们要把用户信息也扩展到JWT
,最简便的方法就是将用户信息写成JSON
字符串替换sub
字段。其中用户信息由xc_user
数据库表存储。
二、重写UserDetailsService
注释掉原来的UserDetailsService
实例。新建一个实现类,如下
@Component
@Slf4j
public class UserServiceImpl implements UserDetailsService {@AutowiredXcUserMapper xcUserMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//根据username查询数据库XcUser xcUser = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>().eq(XcUser::getUsername, username));//用户不存在,返回nullif (xcUser == null){return null;}//用户存在,拿到密码,封装成UserDetails,密码对比由框架进行String password = xcUser.getPassword();//扩展用户信息xcUser.setPassword(null);String userInfo = JSON.toJSONString(xcUser);UserDetails userDetails = User.withUsername(userInfo).password(password).authorities("read").build();return userDetails;}
}
- 如果
XcUser
为null
,返回null
,这里处理了用户不存在的情况。 - 如果用户存在,则获取密码,放到
UserDetails
中,密码比对过程我们不关心,由框架完成。如果使用了加密算法,这里的password
应该是密文。 - 我们可以把用户信息转成JSON字符串放入
withUsername
。这样框架生成JWT时就会把用户信息也放进去。
是的,你没有猜错,UserDetails
只要返回密码框架就能比对成功,不需要再返回username
。
三、Controller解析JWT获取用户信息
写一个工具类,通过Security ContextHolder.getContext()
上下文获取Authentication
然后解析JWT
。
@Slf4j
public class SecurityUtil {public static XcUser getUser(){Authentication authentication = SecurityContextHolder.getContext().getAuthentication();if (authentication instanceof JwtAuthenticationToken) {JwtAuthenticationToken jwtAuth = (JwtAuthenticationToken) authentication;Map<String, Object> tokenAttributes = jwtAuth.getTokenAttributes();Object sub = tokenAttributes.get("sub");return JSON.parseObject(sub.toString(), XcUser.class);}return null;}@Datapublic static class XcUser implements Serializable {//...}
}
JwtAuthenticationToken
是Spring Authorization Server
的一个类,可以帮助我们解析JWT
。
四、后记
从SecurityContextHolder.getContext().getAuthentication()
解析我们放进去的XcUser的方法不止一种,将其打印出来就可以看出,有多个地方包含了XcUser
,例如。
{"authenticated": true,"authorities": [{"authority": "SCOPE_all"}],"credentials": {"audience": ["XcWebApp"],"claims": {"sub": "{\"createTime\":\"2022-09-28 08:32:03\",\"id\":\"48\",\"name\":\"系统管理员\",\"sex\":\"1\",\"status\":\"1\",\"username\":\"admin\",\"utype\":\"101003\"}","aud": ["XcWebApp"],"nbf": "2024-02-08T14:01:16Z","scope": ["all"],"iss": "http://localhost:63070/auth","exp": "2024-02-08T16:01:16Z","iat": "2024-02-08T14:01:16Z","jti": "91df8f15-2096-4e03-a927-877b51bf5997"},"expiresAt": "2024-02-08T16:01:16Z","headers": {"kid": "e14df18d-1c95-441d-80d6-8457f3ceba9e","alg": "RS256"},"id": "91df8f15-2096-4e03-a927-877b51bf5997","issuedAt": "2024-02-08T14:01:16Z","issuer": "http://localhost:63070/auth","notBefore": "2024-02-08T14:01:16Z","subject": "{\"createTime\":\"2022-09-28 08:32:03\",\"id\":\"48\",\"name\":\"系统管理员\",\"sex\":\"1\",\"status\":\"1\",\"username\":\"admin\",\"utype\":\"101003\"}","tokenValue": "eyJraWQiOiJlMTRkZjE4ZC0xYzk1LTQ0MWQtODBkNi04NDU3ZjNjZWJhOWUiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ7XCJjcmVhdGVUaW1lXCI6XCIyMDIyLTA5LTI4IDA4OjMyOjAzXCIsXCJpZFwiOlwiNDhcIixcIm5hbWVcIjpcIuezu-e7n-euoeeQhuWRmFwiLFwic2V4XCI6XCIxXCIsXCJzdGF0dXNcIjpcIjFcIixcInVzZXJuYW1lXCI6XCJhZG1pblwiLFwidXR5cGVcIjpcIjEwMTAwM1wifSIsImF1ZCI6IlhjV2ViQXBwIiwibmJmIjoxNzA3NDAwODc2LCJzY29wZSI6WyJhbGwiXSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo2MzA3MC9hdXRoIiwiZXhwIjoxNzA3NDA4MDc2LCJpYXQiOjE3MDc0MDA4NzYsImp0aSI6IjkxZGY4ZjE1LTIwOTYtNGUwMy1hOTI3LTg3N2I1MWJmNTk5NyJ9.NZ3f_Pkh871L1c8XkV2PxHfn17pWjaRvBd9HQQTRJhfFvNBN7zoh2riumpfVUj_xVmnCadVX3YE4ARxc0CuiV1QyVDpFnmKiuvWdsRVV9NF5Kkb67CGtF2zw1l2gFdSDFWAwOq1SemtogHX5a4XFF2kG6kx9ZOSL4EoiQMMhUOwfY6mL9Zdcgq_E28kfnrAk__q84rgo9JPvj3jH6cm_oS63-tNXZYdClDG61DHS4Bw7cswUfVf_bcI_a8kXfiM8SzCnROvxe1hU2dM88qxUgkI1GPlrtZhe9z7113XP7ilaPo2UknCFh_OSbfUeUDmP1GpTaspfGmnHhBXLQyG06Q"},"details": {"remoteAddress": "192.168.222.1"},"name": "{\"createTime\":\"2022-09-28 08:32:03\",\"id\":\"48\",\"name\":\"系统管理员\",\"sex\":\"1\",\"status\":\"1\",\"username\":\"admin\",\"utype\":\"101003\"}","principal": {"audience": ["XcWebApp"],"claims": {"sub": "{\"createTime\":\"2022-09-28 08:32:03\",\"id\":\"48\",\"name\":\"系统管理员\",\"sex\":\"1\",\"status\":\"1\",\"username\":\"admin\",\"utype\":\"101003\"}","aud": ["XcWebApp"],"nbf": "2024-02-08T14:01:16Z","scope": ["all"],"iss": "http://localhost:63070/auth","exp": "2024-02-08T16:01:16Z","iat": "2024-02-08T14:01:16Z","jti": "91df8f15-2096-4e03-a927-877b51bf5997"},"expiresAt": "2024-02-08T16:01:16Z","headers": {"kid": "e14df18d-1c95-441d-80d6-8457f3ceba9e","alg": "RS256"},"id": "91df8f15-2096-4e03-a927-877b51bf5997","issuedAt": "2024-02-08T14:01:16Z","issuer": "http://localhost:63070/auth","notBefore": "2024-02-08T14:01:16Z","subject": "{\"createTime\":\"2022-09-28 08:32:03\",\"id\":\"48\",\"name\":\"系统管理员\",\"sex\":\"1\",\"status\":\"1\",\"username\":\"admin\",\"utype\":\"101003\"}","tokenValue": "eyJraWQiOiJlMTRkZjE4ZC0xYzk1LTQ0MWQtODBkNi04NDU3ZjNjZWJhOWUiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ7XCJjcmVhdGVUaW1lXCI6XCIyMDIyLTA5LTI4IDA4OjMyOjAzXCIsXCJpZFwiOlwiNDhcIixcIm5hbWVcIjpcIuezu-e7n-euoeeQhuWRmFwiLFwic2V4XCI6XCIxXCIsXCJzdGF0dXNcIjpcIjFcIixcInVzZXJuYW1lXCI6XCJhZG1pblwiLFwidXR5cGVcIjpcIjEwMTAwM1wifSIsImF1ZCI6IlhjV2ViQXBwIiwibmJmIjoxNzA3NDAwODc2LCJzY29wZSI6WyJhbGwiXSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo2MzA3MC9hdXRoIiwiZXhwIjoxNzA3NDA4MDc2LCJpYXQiOjE3MDc0MDA4NzYsImp0aSI6IjkxZGY4ZjE1LTIwOTYtNGUwMy1hOTI3LTg3N2I1MWJmNTk5NyJ9.NZ3f_Pkh871L1c8XkV2PxHfn17pWjaRvBd9HQQTRJhfFvNBN7zoh2riumpfVUj_xVmnCadVX3YE4ARxc0CuiV1QyVDpFnmKiuvWdsRVV9NF5Kkb67CGtF2zw1l2gFdSDFWAwOq1SemtogHX5a4XFF2kG6kx9ZOSL4EoiQMMhUOwfY6mL9Zdcgq_E28kfnrAk__q84rgo9JPvj3jH6cm_oS63-tNXZYdClDG61DHS4Bw7cswUfVf_bcI_a8kXfiM8SzCnROvxe1hU2dM88qxUgkI1GPlrtZhe9z7113XP7ilaPo2UknCFh_OSbfUeUDmP1GpTaspfGmnHhBXLQyG06Q"},"token": {"audience": ["XcWebApp"],"claims": {"sub": "{\"createTime\":\"2022-09-28 08:32:03\",\"id\":\"48\",\"name\":\"系统管理员\",\"sex\":\"1\",\"status\":\"1\",\"username\":\"admin\",\"utype\":\"101003\"}","aud": ["XcWebApp"],"nbf": "2024-02-08T14:01:16Z","scope": ["all"],"iss": "http://localhost:63070/auth","exp": "2024-02-08T16:01:16Z","iat": "2024-02-08T14:01:16Z","jti": "91df8f15-2096-4e03-a927-877b51bf5997"},"expiresAt": "2024-02-08T16:01:16Z","headers": {"kid": "e14df18d-1c95-441d-80d6-8457f3ceba9e","alg": "RS256"},"id": "91df8f15-2096-4e03-a927-877b51bf5997","issuedAt": "2024-02-08T14:01:16Z","issuer": "http://localhost:63070/auth","notBefore": "2024-02-08T14:01:16Z","subject": "{\"createTime\":\"2022-09-28 08:32:03\",\"id\":\"48\",\"name\":\"系统管理员\",\"sex\":\"1\",\"status\":\"1\",\"username\":\"admin\",\"utype\":\"101003\"}","tokenValue": "eyJraWQiOiJlMTRkZjE4ZC0xYzk1LTQ0MWQtODBkNi04NDU3ZjNjZWJhOWUiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ7XCJjcmVhdGVUaW1lXCI6XCIyMDIyLTA5LTI4IDA4OjMyOjAzXCIsXCJpZFwiOlwiNDhcIixcIm5hbWVcIjpcIuezu-e7n-euoeeQhuWRmFwiLFwic2V4XCI6XCIxXCIsXCJzdGF0dXNcIjpcIjFcIixcInVzZXJuYW1lXCI6XCJhZG1pblwiLFwidXR5cGVcIjpcIjEwMTAwM1wifSIsImF1ZCI6IlhjV2ViQXBwIiwibmJmIjoxNzA3NDAwODc2LCJzY29wZSI6WyJhbGwiXSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo2MzA3MC9hdXRoIiwiZXhwIjoxNzA3NDA4MDc2LCJpYXQiOjE3MDc0MDA4NzYsImp0aSI6IjkxZGY4ZjE1LTIwOTYtNGUwMy1hOTI3LTg3N2I1MWJmNTk5NyJ9.NZ3f_Pkh871L1c8XkV2PxHfn17pWjaRvBd9HQQTRJhfFvNBN7zoh2riumpfVUj_xVmnCadVX3YE4ARxc0CuiV1QyVDpFnmKiuvWdsRVV9NF5Kkb67CGtF2zw1l2gFdSDFWAwOq1SemtogHX5a4XFF2kG6kx9ZOSL4EoiQMMhUOwfY6mL9Zdcgq_E28kfnrAk__q84rgo9JPvj3jH6cm_oS63-tNXZYdClDG61DHS4Bw7cswUfVf_bcI_a8kXfiM8SzCnROvxe1hU2dM88qxUgkI1GPlrtZhe9z7113XP7ilaPo2UknCFh_OSbfUeUDmP1GpTaspfGmnHhBXLQyG06Q"},"tokenAttributes": {"sub": "{\"createTime\":\"2022-09-28 08:32:03\",\"id\":\"48\",\"name\":\"系统管理员\",\"sex\":\"1\",\"status\":\"1\",\"username\":\"admin\",\"utype\":\"101003\"}","aud": ["XcWebApp"],"nbf": "2024-02-08T14:01:16Z","scope": ["all"],"iss": "http://localhost:63070/auth","exp": "2024-02-08T16:01:16Z","iat": "2024-02-08T14:01:16Z","jti": "91df8f15-2096-4e03-a927-877b51bf5997"}
}
相关文章:

微服务OAuth 2.1扩展额外信息到JWT并解析(Spring Security 6)
文章目录 一、简介二、重写UserDetailsService三、Controller解析JWT获取用户信息四、后记 一、简介 VersionJava17SpringCloud2023.0.0SpringBoot3.2.1Spring Authorization Server1.2.1Spring Security6.2.1mysql8.2.0 Spring Authorization Server 使用JWT时,前…...
Python@setter用法介绍
Pythonsetter是Python编程语言中的一个关键属性,它简化了Python开发者的编程过程,提高了编程效率。 一、Pythonsetter是什么 Pythonsetter是Python语言中的一个属性,它允许程序员设置Python中的类成员变量。在Python中,属性&…...

格子表单GRID-FORM | 文档网站搭建(VitePress)与部署(Github Pages)
格子表单/GRID-FORM已在Github 开源,如能帮到您麻烦给个星🤝 GRID-FORM 系列文章 基于 VUE3 可视化低代码表单设计器嵌套表单与自定义脚本交互文档网站搭建(VitePress)与部署(Github Pages) 效果预览 格…...

mac无法往硬盘里存东西 Mac硬盘读不出来怎么办 Mac硬盘格式 硬盘检测工具
mac有时候会出现一些问题,比如无法往硬盘里存东西,或者无法往硬盘上拷贝文件。这些问题会给用户带来很大的困扰,影响正常的工作和学习。那么,mac无法往硬盘里存东西,mac无法往硬盘上拷贝怎么办呢?软妹子将为…...
DataX源码分析 reader
系列文章目录 一、DataX详解和架构介绍 二、DataX源码分析 JobContainer 三、DataX源码分析 TaskGroupContainer 四、DataX源码分析 TaskExecutor 五、DataX源码分析 reader 六、DataX源码分析 writer 七、DataX源码分析 Channel 文章目录 系列文章目录前言Reader组件如何处理…...
openssl3.2 - exp - RAND_bytes_ex
文章目录 openssl3.2 - exp - RAND_bytes_ex概述笔记END openssl3.2 - exp - RAND_bytes_ex 概述 生成随机数时, 要检查返回值是否成功, 不能认为一定是成功的(官方文档上有说明). 生成随机数的API, 和库上下文有关系, 使用RAND_bytes_ex()比RAND_bytes()好些. 笔记 /*! * …...
Oracle中怎么设置时区和系统时间
在Oracle数据库中,设置时区和系统时间可以通过多种方法实现。下面是一些常见的方法: 1. 设置数据库的时区 Oracle数据库允许你为每个会话或整个数据库设置时区。 a. 为整个数据库设置时区 你可以使用ALTER DATABASE语句为整个数据库设置时区。例如&a…...
常见的物联网操作系统介绍
物联网(Internet of Things,IoT)是指将各种物理设备、车辆、家用电器、工业设备等通过网络连接起来,实现数据交换和通信的技术。物联网操作系统是管理这些设备并使其能够相互通信的软件平台。以下是一些常见的物联网操作系统&…...
二级C语言笔试10
(总分101,考试时间90分钟) 一、选择题 1. 设有如下关系表: A) TR∩S B) TR∪S C) TRS D) TR/S 2. 在一棵二叉树中,叶子结点共有30个,度为1的结点共有40个,则该二叉树中的总结点数共有( )个。 A) 89 …...

【WebSocket】微信小程序原生组件使用SocketTask 调用星火认知大模型
直接上代码 微信开发者工具-调试器-终端-新建终端 进行依赖安装 npm install base-64 npm install crypto-js 然后顶部工具栏依次点击 工具-构建npm // index.js const defaultAvatarUrl https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQ…...

[1-docker-01]centos环境安装docker
官方参考文档 可以在官方docker桌面版本指导文档里找到适合自己的电脑平台进行参考,或者你是老司机的话直接自己上车。 如果不需要桌面版,也可以在官方docker engine版本指导文档里找到适合自己的平台进行参考,同样,老司机可以自…...

深度学习基础之《深度学习介绍》
一、深度学习与机器学习的区别 1、特征提取方面 机器学习:人工特征提取 分类算法 深度学习:没有人工特征提取,直接将特征值传进去 (1)机器学习的特征工程步骤是要靠手工完成的,而且需要大量领域专业知识…...

4核8g服务器能支持多少人访问?2024新版测评
腾讯云轻量4核8G12M轻量应用服务器支持多少人同时在线?通用型-4核8G-180G-2000G,2000GB月流量,系统盘为180GB SSD盘,12M公网带宽,下载速度峰值为1536KB/s,即1.5M/秒,假设网站内页平均大小为60KB…...

Linux中pipe管道操作
管道的读写操作: 读操作: 有数据:read正常读,返回读出的字节数无数据:1 写段全部关闭:read解除阻塞,返回0,相当于文件读到了尾部 2 写段没有全部关闭…...

中年中产程序员从西安出发到海南三亚低成本吃喝万里行:西安-南宁-湛江-雷州-徐闻-博鳌-陵水-三亚-重庆-西安(2.游玩过程)
文章大纲 出发时间:Day1-1月25日星期四,西安飞南宁路途中:Day2-1月26日星期五,南宁-湛江-住雷州(曾经支教过的地方)【晚上买徐闻到海安新港】路途中:Day3-1月27日星期六,雷州-徐闻渡…...
day38 面向对象编程、构造函数等(纯概念)
目录 深入对象构造函数实例成员静态成员内置构造函数ObjectArray包装类型StringNumber 深入对象 了解面向对象的基础概念,能够利用构造函数创建对象。 构造函数 构造函数是专门用于创建对象的函数,如果一个函数使用 new 关键字调用,那么这…...
nginx用域名http://xx.com/aaa/代理一个网页http://ff.com但是请求资源时发生404
哎,还得是chatgpt,难道就没有人有这种使用场景吗?没查到一个配置是有效的。 我: 我配置了nginx反向代理,用域名http://xx.com/aaa/代理一个网页http://ff.com, 但是请求资源时发生404,如何解决&…...

NLP_词的向量表示Word2Vec 和 Embedding
文章目录 词向量Word2Vec:CBOW模型和Skip-Gram模型通过nn.Embedding来实现词嵌入Word2Vec小结 词向量 下面这张图就形象地呈现了词向量的内涵:把词转化为向量,从而捕捉词与词之间的语义和句法关系,使得具有相似含义或相关性的词语在向量空间…...
python:xml.etree 生成思维导图 Freemind文件
请参阅:java : pdfbox 读取 PDF文件内书签 或者 python:从PDF中提取目录 请注意:书的目录.txt 编码:UTF-8,推荐用 Notepad 转换编码。 xml 是 python 标准库,在 D:\Python39\Lib\xml\etree python 用 xm…...

Solidworks:从2D走向3D
Sokidworks 的强大之处在于三维实体建模,这个形状看似复杂,实际上只需要拉伸一次,再做一次减法拉伸就行了。第一次做三维模型,费了不少时间才搞明白。 接下来做一个稍微复杂一点的模型,和上面这个操作差不多࿰…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...