Spring Security 的TokenStore三种实现方式
博主介绍:✌专注于前后端领域开发的优质创作者、秉着互联网精神开源贡献精神,答疑解惑、坚持优质作品共享。本人是掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战,深受全网粉丝喜爱与支持✌有需要可以联系作者我哦!
🍅文末三连哦🍅
什么是Token Store
在Web开发中,Token Store 通常用于存储用户身份验证令牌(Tokens),例如 JSON Web Tokens (JWT) 或其他形式的令牌。这些令牌可以用于验证用户身份,实现用户会话管理以及访问控制。
一种简单的Token Store示例,使用Node.js和Express框架以及一个基于内存的Token存储方式:
const express = require('express');
const jwt = require('jsonwebtoken');const app = express();
app.use(express.json());// In-memory Token Store
const tokenStore = {};// Secret key for JWT (replace with a strong, secret key in production)
const secretKey = 'your_secret_key';// Middleware to verify JWT
function verifyToken(req, res, next) {const token = req.headers.authorization;if (!token) {return res.status(403).json({ message: 'No token provided' });}jwt.verify(token, secretKey, (err, decoded) => {if (err) {return res.status(401).json({ message: 'Failed to authenticate token' });}req.user = decoded;next();});
}// Endpoint to generate and return a JWT
app.post('/login', (req, res) => {const { username, password } = req.body;// Authenticate user (replace with your actual authentication logic)// For simplicity, assume any username and password combination is validconst user = { username, role: 'user' };// Generate a JWTconst token = jwt.sign(user, secretKey, { expiresIn: '1h' });// Store the token in memorytokenStore[token] = user;res.json({ token });
});// Protected endpoint that requires a valid JWT for access
app.get('/protected', verifyToken, (req, res) => {res.json({ message: 'This is a protected endpoint', user: req.user });
});// Start the server
const port = 3000;
app.listen(port, () => {console.log(`Server is running on http://localhost:${port}`);
});
Spring Security 提供了几个常见的
TokenStore
实现,包括内存中存储、JDBC 数据库存储和基于 JWT(JSON Web Token)的存储。下面将分别介绍这三种实现方式,并提供基本的代码示例。
1. 内存中存储(In-Memory)
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Beanpublic TokenStore inMemoryTokenStore() {return new InMemoryTokenStore();}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("client").secret("{noop}secret") // 使用 "{noop}" 表示不加密.authorizedGrantTypes("password", "authorization_code", "refresh_token").scopes("read", "write").accessTokenValiditySeconds(3600).refreshTokenValiditySeconds(86400);}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.tokenStore(inMemoryTokenStore()).authenticationManager(authenticationManager);}
}
2. JDBC 数据库存储
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate DataSource dataSource;@Beanpublic TokenStore jdbcTokenStore() {return new JdbcTokenStore(dataSource);}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.jdbc(dataSource);}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.tokenStore(jdbcTokenStore()).authenticationManager(authenticationManager);}
}
3. 基于 JWT 的存储
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Value("${security.jwt.client-id}")private String clientId;@Value("${security.jwt.client-secret}")private String clientSecret;@Value("${security.jwt.grant-type}")private String grantType;@Value("${security.jwt.scope-read}")private String scopeRead;@Value("${security.jwt.scope-write}")private String scopeWrite;@Value("${security.jwt.resource-ids}")private String resourceIds;@Beanpublic TokenStore jwtTokenStore() {return new JwtTokenStore(jwtAccessTokenConverter());}@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setSigningKey("secret");return converter;}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient(clientId).secret("{noop}" + clientSecret).authorizedGrantTypes(grantType).scopes(scopeRead, scopeWrite).resourceIds(resourceIds);}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.tokenStore(jwtTokenStore()).accessTokenConverter(jwtAccessTokenConverter()).authenticationManager(authenticationManager);}
}
小结
我们介绍了Spring Security中三种不同的Token Store实现方式。具体包括内存中存储、JDBC数据库存储和基于JWT的存储。每个实现方式都涉及到授权服务器的配置,用于管理和验证令牌,以及客户端详情的配置。
大家点赞、收藏、关注、评论啦!谢谢三连哦!
相关文章:
Spring Security 的TokenStore三种实现方式
博主介绍:✌专注于前后端领域开发的优质创作者、秉着互联网精神开源贡献精神,答疑解惑、坚持优质作品共享。本人是掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战,深受全网粉丝喜爱与支持✌有需要可以联系作者我哦&…...
微信小程序 图片自适应高度 宽度 完美适配原生或者uniapp
-- - - - 查了一下百度看到网上图片高度自适应的解决方案 基本是靠JS获取图片的宽度进行按比例计算得出图片高度。 不是很符合我的需求/ 于是我脑瓜子一转 想到一种新的解决方案 不用JS计算也能完美解决。 我写了一个组件,直接导入可以使用。 - - - 1.新…...
Go语言基础之反射
1.变量的内在机制 Go语言中的变量是分为两部分的: 类型信息:预先定义好的元信息。值信息:程序运行过程中可动态变化的。 2.反射介绍 反射是指在程序运行期间对程序本身进行访问和修改的能力。程序在编译时,变量被转换为内存地址ÿ…...

MySQL十部曲之六:数据操作语句(DML)
文章目录 前言语法约定DELETEINSERTSELECT查询列表SELECT 选项子句FROMWHEREORDER BYGROUP BYHAVINGWINDOWLIMITFOR SELECT ... INTO连接查询CROSS JOIN和INNER JOINON和USINGOUTER JOINNATURE JOIN 子查询标量子查询使用子查询进行比较带有ANY、IN或SOME的子查询带有ALL的子查…...

Quartus生成烧录到FPGA板载Flash的jic文件
简要说明: Altera的FPGA芯片有两种基本分类,一类是纯FPGA,另一类是FPGASoc(System on chip),也就是FPGAHPS(Hard Processor System,硬核处理器),对应两种Flash烧录方式&a…...

CSS 多色正方形上升
<template><view class="loop cubes"><view class="item cubes"></view> <!-- 方块1 --><view class="item cubes"></view> <!-- 方块2 --><view class="item cubes"></vie…...

《HelloGitHub》第 94 期
兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 https://github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等,涵盖多种编程语言 …...

uniapp 实现路由拦截,权限或者登录控制
背景: 项目需要判断token,即是否登录,登录之后权限 参考uni-app官方: 为了兼容其他端的跳转权限控制,uni-app并没有用vue router路由,而是内部实现一个类似此功能的钩子:拦截器,由…...

[GXYCTF2019]BabySQli1
单引号闭合,列数为三列,但是没有期待的1 2 3回显,而是显示wrong pass。 尝试报错注入时发现过滤了圆括号,网上搜索似乎也没找到能绕过使用圆括号的方法,那么按以往爆库爆表爆字段的方法似乎无法使用了 在响应报文找到一…...

【架构】Docker实现集群主从缩容【案例4/4】
实现集群主从缩容【4/4】 接上一节,在当前机器为4主4从的架构上,减缩容量为3主3从架构。即实现删除6387和6388. 示意图如下: 第一步:查看集群情况(第一次) redis-cli --cluster check 127.0.0.1:6387roo…...
【ArcGIS微课1000例】0097:栅格重采样(以数字高程模型dem为例)
Contents 1. 最邻近法(Nearest Neighbor)2. 双线性内插法(Bilinear Interpolation)3. 三次卷积法(Cubic Convolution)4. ArcGIS重采样工具(Resample)5. 注意事项栅格/影像数据进行配准或纠正、投影等几何变换后,像元中心位置通常会发生变化,其在输入栅格中的位置不一…...

【技术分享】Ubuntu 20.04如何更改用户名
产品简介 本文适用于所有RK3568/RK3588平台产品在Ubuntu 20.04系统上如何更改用户名,本文以IDO-EVB3588开发板为例,在ubuntu20.04系统上修改用户名industio为usernew。 IDO-EVB3588开发板是一款基于RK3588平台的产品。该开发板集成了四核Cortex-A76和四…...

LabVIEW振动信号分析
LabVIEW振动信号分析 介绍如何使用LabVIEW软件实现希尔伯特-黄变换(Hilbert-Huang Transform, HHT),并将其应用于振动信号分析。HHT是一种用于分析非线性、非平稳信号的强大工具,特别适用于旋转机械等复杂系统的振动分析。开发了…...
清理Docker环境
清理Docker环境:有时,Docker环境可能会出现一些问题,导致网络连接故障。您可以尝试清理Docker环境并重新启动。可以尝试运行以下命令: 复制 docker-compose down docker system prune -a docker-compose up docker-compose up 和…...

oracle等保测评
实战|等保2.0 Oracle数据库测评过程 一、身份鉴别 a) 应对登录的用户进行身份标识和鉴别,身份标识具有唯一性,身份鉴别信息具有复杂度要求并定期更换; sysdba是Oracle数据库的最高权限管理员。通常使用sqlplus或PL/SQL 管理软件进行管理,PL/SQL 为第三方管理软件,但S…...

x-cmd pkg | go - Google 开发的开源编程语言
目录 简介首次用户技术特点竞品分析编译型语言解释型语言JavaWebAssebmly 进一步阅读 简介 Go 语言(或 Golang)是 Google 开发的开源编程语言,诞生于 2006 年。其设计目标是“兼具 Python 等动态语言的开发速度和 C/C 等编译型语言的性能与安…...

32个Java面试必考点-09(下)MySQL调优与最佳实践
详解 MySQL 下面来学习互联网行业使用最为广泛的关系型数据库 MySQL,它的知识点结构图如下所示。 常用 SQL 语句 对于手写常用 SQL 语句,没有什么特殊的技巧,根据所列的语句类型多做一些练习就好。 数据类型 要知道 MySQL 都提供哪些基本的…...

优思学院|精益管理如何判定哪些活动是增值或非增值?
“时间就是金钱”——这句老话我们都耳熟能详。但在工作中,我们真正从事的、对组织增加价值的活动有多少呢?我们常常认为自己的每一项任务都是维持运营的关键。然而,当我们从精益管理的视角进行分析,可能会惊讶地发现,…...

详解操作系统各章大题汇总(死锁资源分配+银行家+进程的PV操作+实时调度+逻辑地址->物理地址+页面置换算法+磁盘调度算法)
文章目录 第三章:死锁资源分配图例一例二 第三章:银行家算法第四章:进程的同步与互斥做题步骤PV操作的代码小心容易和读者写者混 1.交通问题(类似读者写者)分析代码 2.缓冲区问题(第二个缓冲区是复制缓冲区…...

用ASM HEMT模型提取GaN器件的参数
标题:Physics-Based Multi-Bias RF Large-Signal GaNHEMT Modeling and Parameter Extraction Flow (JEDS 17年) 模型描述 该模型的核心是对表面势(ψ)及其随施加的栅极电压(Vg)和漏极电压(Vd)…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...