SpringSecurity+jwt+captcha登录认证授权总结
SpringSecurity+jwt+captcha登录认证授权总结
版本信息:
springboot 3.2.0、springSecurity 6.2.0、mybatis-plus 3.5.5
认证授权思路和流程:
未携带token,访问登录接口:
1、用户登录携带账号密码
2、请求到达自定义Filter,自定义Filter(如JwtAuthenticationTokenFilter)继承OncePerRequestFilter(此Filter只会进行一次过滤,在请求返回时,不会再进行调用),在SecurityConfig中配置,将自定义Filter添加到过滤器链中并加在UsernamePasswordAuthenticationFilter过滤器之前
3、自定义Filter逻辑
3.1、查询到用户未携带token,直接放行,进入到后面认证流程
3.2、将用户信息封装成Authentication对象,调用authticate()方法进行验证,一直到DaoAuthenticationProvider中,会调用UserDetailService的loadUserByUserName()方法;自定义UserDetailServiceImpl继承UserDetailService接口;重写其loadUserByUserName()方法;查到用户后,封装成UserDetail对象返回
4、调用passwordEncoder的验证方法进行用户信息的认证(一般使用BCryptPasswordEncoder,创建此Bean并放入容器中)
5、认证通过后,使用JWT创建token并放到redis中;返回token到前端
携带token访问:
1、请求到达自定义Filter中,获取token,先验证token的正确性,从token中获取到userId,根据userId从redis中获取用户信息,将用户信息封装成Authentication对象,放进SecurityContextHolder中,后面的过滤器会在SecurityContextHolder中获取用户的信息
2、请求到达FilterSecurityInterceptor,在springSecurity中默认使用FilterSecurityInterceptor来进行权限校验;FilterSecurityInterceptor会从SecurityContextHolder中获取Authentication,然后获取其中的权限信息,判断当前用户是否拥有当前资源的访问权限;
3、通过权限判断,获取资源返回给前端;
登录认证流程图:
基于RBAC的授权控制:
RBAC概念:
Role-Based Access Control,中文意思是:基于角色(Role)的访问控制。这是一种广泛应用于计算机系统和网络安全领域的访问控制模型。
简单来说,就是通过将权限分配给角色,再将角色分配给用户,来实现对系统资源的访问控制。一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成“用户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权限之间,一般是多对多的关系
模型:
在数据库中主要体现用户表、角色表、菜单表、用户角色关联表、角色菜单关联表五个模型:
CREATE TABLE "mySchema"."t_user"
(
"id" INT IDENTITY(1, 1) NOT NULL,
"username" VARCHAR(100) NOT NULL,
"password" VARCHAR(100) NOT NULL,
"email" VARCHAR(100) NOT NULL,
"phone" VARCHAR(100),
UNIQUE("id"),
UNIQUE("username"),
UNIQUE("email"),
UNIQUE("phone"),
NOT CLUSTER PRIMARY KEY("id")) STORAGE(ON "MAIN", CLUSTERBTR) ;COMMENT ON TABLE "mySchema"."t_user" IS '用户表';
COMMENT ON COLUMN "mySchema"."t_user"."id" IS '用户id';
COMMENT ON COLUMN "mySchema"."t_user"."username" IS '用户名';
COMMENT ON COLUMN "mySchema"."t_user"."password" IS '密码';
COMMENT ON COLUMN "mySchema"."t_user"."email" IS '用户邮箱';
COMMENT ON COLUMN "mySchema"."t_user"."phone" IS '电话';CREATE TABLE "mySchema"."sys_role"
(
"id" BIGINT IDENTITY(1, 1) NOT NULL,
"name" VARCHAR(128) DEFAULT NULL,
"role_key" VARCHAR(100) DEFAULT NULL,
"status" CHAR(1) DEFAULT '0',
"del_flag" INT DEFAULT 0,
"create_by" BIGINT DEFAULT NULL,
"create_time" DATETIME(6) DEFAULT NULL,
"update_by" BIGINT DEFAULT NULL,
"update_time" DATETIME(6) DEFAULT NULL,
"remark" VARCHAR(500) DEFAULT NULL,
NOT CLUSTER PRIMARY KEY("id")) STORAGE(ON "MAIN", CLUSTERBTR) ;COMMENT ON TABLE "mySchema"."sys_role" IS '角色表';
COMMENT ON COLUMN "mySchema"."sys_role"."id" IS '角色id';
COMMENT ON COLUMN "mySchema"."sys_role"."name" IS '角色名称';
COMMENT ON COLUMN "mySchema"."sys_role"."role_key" IS '角色权限字符串';
COMMENT ON COLUMN "mySchema"."sys_role"."status" IS '角色状态(0正常, 1停用)';
COMMENT ON COLUMN "mySchema"."sys_role"."del_flag" IS '删除标志(0未删除,1已删除)';
COMMENT ON COLUMN "mySchema"."sys_role"."remark" IS '备注';CREATE TABLE "mySchema"."sys_menu"
(
"id" BIGINT IDENTITY(2, 1) NOT NULL,
"menu_name" VARCHAR(64) DEFAULT 'NULL' NOT NULL,
"path" VARCHAR(200) DEFAULT NULL,
"component" VARCHAR(50) DEFAULT NULL,
"visible" CHAR(1) DEFAULT '0',
"status" CHAR(1) DEFAULT '0',
"perms" VARCHAR(100) DEFAULT NULL,
"icon" VARCHAR(100) DEFAULT '#',
"create_by" BIGINT DEFAULT NULL,
"create_time" DATETIME(6) DEFAULT CURRENT_TIMESTAMP,
"update_by" BIGINT DEFAULT NULL,
"update_time" DATETIME(6) DEFAULT CURRENT_TIMESTAMP,
"delete_f1ag" INT DEFAULT 0,
"remark" VARCHAR(500) DEFAULT NULL,
UNIQUE("id"),
NOT CLUSTER PRIMARY KEY("id")) STORAGE(ON "MAIN", CLUSTERBTR) ;COMMENT ON TABLE "mySchema"."sys_menu" IS '菜单表';
COMMENT ON COLUMN "mySchema"."sys_menu"."menu_name" IS '菜单名';
COMMENT ON COLUMN "mySchema"."sys_menu"."path" IS '路由地址';
COMMENT ON COLUMN "mySchema"."sys_menu"."component" IS '组件路径';
COMMENT ON COLUMN "mySchema"."sys_menu"."visible" IS '菜单状态(0显示1隐藏)';
COMMENT ON COLUMN "mySchema"."sys_menu"."status" IS '菜单状态(0正常1停用)';
COMMENT ON COLUMN "mySchema"."sys_menu"."perms" IS '权限标识';
COMMENT ON COLUMN "mySchema"."sys_menu"."icon" IS '菜单图标';
COMMENT ON COLUMN "mySchema"."sys_menu"."delete_f1ag" IS '是否删除(0未删除1已删除)';
COMMENT ON COLUMN "mySchema"."sys_menu"."remark" IS '备注';CREATE TABLE "mySchema"."sys_user_role"
(
"user_id" BIGINT DEFAULT 0 NOT NULL,
"role_id" BIGINT DEFAULT 0 NOT NULL,
NOT CLUSTER PRIMARY KEY("user_id", "role_id")) STORAGE(ON "MAIN", CLUSTERBTR) ;COMMENT ON TABLE "mySchema"."sys_user_role" IS '用户角色表';
COMMENT ON COLUMN "mySchema"."sys_user_role"."user_id" IS '用户id';
COMMENT ON COLUMN "mySchema"."sys_user_role"."role_id" IS '角色id';CREATE TABLE "mySchema"."sys_role_menu"
(
"role_id" BIGINT DEFAULT 0 NOT NULL,
"menu_id" BIGINT DEFAULT 0 NOT NULL,
NOT CLUSTER PRIMARY KEY("role_id", "menu_id")) STORAGE(ON "MAIN", CLUSTERBTR) ;COMMENT ON TABLE "mySchema"."sys_role_menu" IS '角色菜单关联表';
COMMENT ON COLUMN "mySchema"."sys_role_menu"."role_id" IS '角色id';
COMMENT ON COLUMN "mySchema"."sys_role_menu"."menu_id" IS '菜单id';
权限流程:
用户表、角色表、菜单表、部门表、用户角色关联表、角色菜单关联表;数据权限分为5种:个人、全部、本部门、指定部门、本部门及以下
链路:
1、用户注册,指定部门;创建角色,给角色赋菜单权限、数据权限;给用户赋予角色;
2、用户登录,通过用户的所有角色,获取所有的菜单权限和最大数据权限;菜单数据直接展示在页面;所有数据都有创建人,则数据的部门id是创建人的部门id;
3、在访问数据接口时,通过mybatis的拦截器对用户的数据进行过滤(拼接sql),返回给前端;
captcha图片验证码:
实现思路:
1、图片验证码获取,并将验证码验证码存放起来(单机应用可放在session中,分布式应用放在redis中)
2、当用户登录时,携带验证码以及验证码的key,进入到后端从redis中获取值进行验证
<!-- 谷歌kaptcha验证码依赖 -->
<dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version>
</dependency>
代码思路:
1、生成验证码
public Result<CaptchaVO> getCaptcha() throws IOException {// 生成文字验证码String content = defaultKaptcha.createText();// 生成图片验证码ByteArrayOutputStream outputStream = null;BufferedImage image = defaultKaptcha.createImage(content);outputStream = new ByteArrayOutputStream();ImageIO.write(image, "jpg", outputStream);// 对字节数组Base64编码String str = "data:image/jpeg;base64,";String base64Img = str + Base64.getEncoder().encodeToString(outputStream.toByteArray()).replace("\n", "").replace("\r", "");CaptchaVO captchaVO = captchaService.cacheCaptcha(content);captchaVO.setBase64Img(base64Img);return Result.success(captchaVO);
}
2、存储验证码
@Service
public class CaptchaService {private Long timeout = 300L;@Autowiredprivate RedisUtils redisUtils;private final String CAPTCHA_KEY_PREFIX = "captcha:verification:";public CaptchaVO cacheCaptcha(String captcha){//生成一个随机标识符String randomStr = UUID.randomUUID().toString();//缓存验证码并设置过期时间String captchaKey = CAPTCHA_KEY_PREFIX.concat(randomStr);redisUtils.set(captchaKey, captcha, timeout, TimeUnit.SECONDS);CaptchaVO captchaVO = new CaptchaVO();captchaVO.setCaptchaKey(captchaKey);captchaVO.setExpire(timeout);captchaVO.setCaptcha(captcha);return captchaVO;}
}
3、校验验证码
Object captcha = redisUtils.get(reqVO.getCaptchaKey());
if (Objects.isNull(captcha)) {return "验证码已过期";
}
if (!captcha.equals(reqVO.getCaptcha())) {return "验证码错误";
}
相关文章:

SpringSecurity+jwt+captcha登录认证授权总结
SpringSecurityjwtcaptcha登录认证授权总结 版本信息: springboot 3.2.0、springSecurity 6.2.0、mybatis-plus 3.5.5 认证授权思路和流程: 未携带token,访问登录接口: 1、用户登录携带账号密码 2、请求到达自定义Filter&am…...

项目技术栈-解决方案-web3去中心化
web3去中心化 Web3 DApp区块链:钱包:智能合约:UI:ETH系开发技能树DeFi应用 去中心化金融P2P 去中心化网络参考Web3 DApp 区块链: 以以太坊(Ethereum)为主流,也包括Solana、Aptos等其他非EVM链。 区块链本身是软件,需要运行在一系列节点上,这些节点组成P2P网络或者半…...

【AI声音克隆整合包及教程】第二代GPT-SoVITS V2:创新与应用
一、引言 随着科技的迅猛发展,声音克隆技术已经成为一个炙手可热的研究领域。SoVITS(Sound Voice Intelligent Transfer System),作为该领域的先锋,凭借其卓越的性能和广泛的适用性,正在为多个行业带来前所…...

分清数据链路层、网络层、传输层的区别,以及这些层面的代表协议
目录 数据链路层 网络层 传输层 数据链路层 OSI模型的第二层,负责在相邻节点之间传输帧,处理帧的封装、地址、差错控制和流量控制等。确保数据在物理介质上可靠地传输,并为上层协议提供服务。 以太网(Ethernet)&…...

git没有识别出大写字母改成小写重命名的文件目录
Git 默认不会跟踪大写字母和小写字母的区别,因为在大多数文件系统中,大写字母和小写字母被认为是相同的文件,只有在区分大小写的文件系统中(如 macOS 的 HFS 或 Windows 的 NTFS),这才是一个问题。 如果重命…...

自己动手写Qt Creator插件
文章目录 前言一、环境准备1.先看自己的Qt Creator IDE的版本2.下载源码 二、使用步骤1.参考原本的插件2.编写自定义插件1.cmakelist增加一个模块2.同理,qbs文件也增加一个3.插件源码 三、效果总结 前言 就目前而言,Qt Creator这个IDE,插件比…...

数据重塑:长宽数据转换【基于tidyr】
在数据分析和可视化过程中,数据的组织形式直接影响着我们能够进行的分析类型和可视化效果。这里简单介绍两种常见的数据格式:长格式(Long Format)和宽格式(Wide Format),以及如何使用tidyr包进行…...

多模态大模型开启AI社交新纪元,Soul App创始人张璐团队亮相2024 GITEX GLOBAL
随着AI在全球范围内的加速发展和广泛应用,各行业纷纷在此领域发力。作为全球最大的科技盛会之一,2024年的GITEX GLOBAL将目光再次聚焦于人工智能的飞速发展,吸引了超过6700家来自各个领域的企业参与。在这样的背景下,Soul App作为国内较早将AI技术应用于社交领域的平台,首次亮相…...

实验6记录网络与故障排除
实验6记录网络与故障排除 实验目的及要求: 通过实验,掌握如何利用文档记录网络设备相关信息并完成网络拓扑结构的绘制。能够使用各种技术和工具来找出连通性问题,使用文档来指导故障排除工作,确定具体的网络问题,实施…...

QEMU 模拟器中运行的 Linux 系统
这两个文件通常用于在 QEMU 模拟器中运行的 Linux 系统,具体作用如下: 1. linux-aarch64-qemu.ext4: - **文件类型**:这是一个文件系统镜像文件,通常是 ext4 文件系统格式。 - **作用**:它包含了 Li…...

Ceph PG(归置组)的状态说明
Ceph PG(Placement Group)的状态反映了Ceph集群中数据的健康状况和分布情况。以下是Ceph PG的一些常见状态: Creating:创建状态。在创建存储池时,会创建指定数量的归置组(PG)。Ceph在创建一或多…...

Docker使用docker-compose一键部署nacos、Mysql、redis
下面是一个简单的例子,展示如何通过Docker Compose文件部署Nacos、MySQL和Redis。请确保您的机器上已经安装了Docker和Docker Compose。 1,准备好mysql、redis、nacos镜像 sudo docker pull mysql:8 && sudo docker pull redis:7.2 &&…...

HTTP常见的状态码有哪些,都代表什么意思
HTTP 协议定义了一系列的状态码,用于描述服务器对客户端请求的处理结果。这些状态码分为五个类别,每个类别都有特定的用途。 常见状态码 1开头 信息性状态码 这些状态码表示请求已被接收,继续处理。 100 Continue:客户端应继续…...

WebKit的Windows接口(适用2024年11月份版)
WebKit的Windows接口 使用cairo作为图形后端,libcurl作为网络后端。并且它只支持64位的Windows。 安装开发工具 安装带有“使用c进行桌面开发”工作负载的最新Visual Studio。 Activate Developer Mode.激活开发者模式。Build-webkit脚本创建一个指向生成的comp…...

Android 最新的AndroidStudio引入依赖失败如何解决?如:Failed to resolve:xxxx
错误信息: 在引入依赖时报错:Failed to resolve: xxx.xxxx:1.1.0 解决方案: 需要修改maven库的代理,否则就需要翻墙编译 新的AndroidStudio版本比较坑,修改代理的位置发生了变化: 最新变化:…...

ue5 蓝图学习(一)结构体的使用
在内容浏览器中右键 蓝图-选择结构体 下面这东西就是结构体,和C的结构体差不多 双击一下 可以添加变量,设置变量的类型和默认值。 可以在关卡蓝图中调用它。 点击打开关卡蓝图,添加变量 在变量的右侧,变量类型里搜索strcut&#…...

docker--工作目录迁移
前言 安装docker,默认的情况容器的默认存储路径会存储系统盘的 /var/lib/docker 目录下,系统盘一般默认 50G,容器输出的所有的日志,文件,镜像,都会存在这个地方,时间久了就会占满系统盘。 一、…...

Golang | Leetcode Golang题解之第556题下一个更大元素III
题目: 题解: func nextGreaterElement(n int) int {x, cnt : n, 1for ; x > 10 && x/10%10 > x%10; x / 10 {cnt}x / 10if x 0 {return -1}targetDigit : x % 10x2, cnt2 : n, 0for ; x2%10 < targetDigit; x2 / 10 {cnt2}x x2%10 -…...

2分钟在阿里云ECS控制台部署个人应用(图文示例)
作为一名程序员,我有大量的个人代码和应用托管在Github/Gitee这些代码仓库。当我想要部署这些代码到我的阿里云ECS服务器时,往往会很麻烦,主要问题有这些: 需要手动安装和配置git,过程非常繁琐。每次都需要登录到机器…...

2023.8 用于生物医学问答的选择性 UMLS 知识注入
Selective UMLS knowledge infusion for biomedical question answering Selective UMLS knowledge infusion for biomedical question answering | Scientific Reports 韩国首尔国立大学研究生院生物工程跨学科项目 问题 如何高效地将生物医学知识注入预训练语言模型&#x…...

chat2db调用ollama实现数据库的操作。
只试了mysql的调用。 其它的我也不用,本来想充钱算了。最后一看单位是美刀。就放弃了这分心。于是折腾了一下。 本地运行chat2db 及chat2db ui https://gitee.com/ooooinfo/Chat2DB clone 后运行起来 chat2db的java端,我现在搞不清这一个项目是有没有…...

Rust 生态系统的未来与学习方向
Rust 生态系统的未来与学习方向 Rust 作为一门系统编程语言,因其内存安全性、并发性能以及生态的不断壮大,已逐渐成为开发者和企业的首选语言之一。随着技术的进步,Rust 的生态系统持续发展,涉及多个领域,包括 Web 开…...

Vue的基础使用
一、为什么要学习Vue 1.前端必备技能 2.岗位多,绝大互联网公司都在使用Vue 3.提高开发效率 4.高薪必备技能(Vue2Vue3) 二、什么是Vue 概念:Vue (读音 /vjuː/,类似于 view) 是一套 构建用户界面 的 渐进式 框架…...

c++中,头文件包含iostream.h和`<iostream>`的差别
引言 在编写c代码时,有时候包含头文件iostream.h,有时候又包含<iostream>,初学者会对此感到很疑惑。 实际上,这两者是同一个头文件,只是包含方式不同,这是由于C的历史原因造成的,下面解释…...

界面控件DevExpress WPF中文教程:TreeList视图及创建分配视图
DevExpress WPF拥有120个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…...

软件工程笔记二—— 软件生存期模型
目录 瀑布模型 瀑布模型的特点 阶段间具有顺序性和依赖性。 推迟实现的观点 质量保证的观点 瀑布模型的优点 瀑布模型的缺点 快速原型模型 快速原型模型的优点 快速原型模型的缺点 增量模型 增量模型的优点 增量构件开发 螺旋模型 完整的螺旋模型(顺…...

关于若依500验证码问题的求助
关于若依框架中验证码出现500错误的问题,这通常表示服务器内部错误。以下是一些可能的原因及解决方案: 一、配置文件问题 .env.production文件: 确保.env.production文件中的VUE_APP_BASE_API已经修改成服务器上的域名地址,而不…...

网络安全:守护数字世界的坚固防线
随着信息技术的飞速发展,网络已成为我们生活中不可或缺的一部分。它为我们提供了便捷的信息获取、交流娱乐的渠道,但同时也带来了前所未有的安全挑战。网络安全,这一看似遥远却又紧密相连的概念,正日益成为我们共同关注的焦点。 …...

Vue前端开发,组件及组件的使用
什么是组件 组件(Component)是Vue中最强大的功能之一,每个Vue 文件就是一个个独立的组件,组件也可以被其他组件调用,形成嵌套关系,大部分的应用都是由各类不同功能的小组件进行构建,形成一个功能强大的大组件树系统&a…...

from sklearn.feature_selection import VarianceThreshold.移除低方差的特征来减少数据集中的特征数量
VarianceThreshold 是 scikit-learn 库中的一个特征选择类,它通过移除低方差的特征来减少数据集中的特征数量。这种方法特别适用于删除那些在整个数据集中几乎不变的特征,因为这些特征对于模型的预测能力贡献不大。 参数: threshold&#x…...