微服务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 的强大之处在于三维实体建模,这个形状看似复杂,实际上只需要拉伸一次,再做一次减法拉伸就行了。第一次做三维模型,费了不少时间才搞明白。 接下来做一个稍微复杂一点的模型,和上面这个操作差不多࿰…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
