百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

springsecurity实现前后端分离项目中的认证和授权

ztj100 2025-04-30 21:20 1 浏览 0 评论

以一个最基础的用户管理系统为例,要实现以下功能:

  • 用户密码加密
  • 支持通过用户名、手机号、邮箱 + 密码登录
  • 手机号登录支持短信验证码登录,邮箱登录支持邮件验证码登录
  • 用户登录成功后,之后的请求通过JWT令牌验证身份信息
  • 对于需要保护的接口,进行权限检查

准备工作

1.设计表,并填充数据

使用典型的RBAC模型,共有5张表:

用户表: t_ums_user

角色表: t_ums_role

用户-角色关系表: t_ums_user_role

权限表: t_permission

角色-权限关系表: t_role_permission

2.创建springboot工程,并创建启动类

springboot版本为2.5.14

添加依赖

创建启动类

3.创建数据表对应的实体类

省略每个实体的getter和setter方法

用户

角色

用户-角色

权限

角色-权限

4.集成mybatis


mybatis-spring-boot-starter版本为2.2.2,mysql-connector-java版本为8.0.27

添加mybatis和mysql依赖

在application.yml文件中配置数据源,以及mybatis相关的配置

5.创建每个实体对应的Controller,Mapper接口及其XML映射文件

这里去掉了Service层

5.1 实现发送验证码接口

Validator类:声明用于校验用户名、手机号、邮箱的正则表达式

Cache类:用HashMap模拟一个缓存数据库(实际生产中使用Redis等高性缓存能数据库)

VerifyCodeController:定义发送验证码接口

这里并没有真的去发送验证码,只在控制台中输出。

测试接口

控制台中输出了验证码

5.2 实现增删改查方法

这里只列出必要的增删改查方法

Mapper 接口定义如下,只有UMSUserMapper接口中定义了几个方法

Mapper XML映射文件如下

5.3 实现控制器

作为示例,只在UMSUserController中定义了3个控制器方法:用户注册、查询用户信息、查询用户列表

其中,用户注册方法定义如下

密码加密部分需要用到springsecurity中的api,后续完成

6.引入springsecurity

添加springsecurity依赖

创建一个配置类,用于自定义security

身份认证

配置请求资源拦截规则

  • 获取验证码接口,放行全部
  • 注册接口,放行全部
  • 查看用户信息接口,需要进行身份认证
  • 其它的请求,全部拒绝访问

密码加密

只需要在spring容器中注入一个PasswordEncoder即可

完成注册接口中密码加密部分的代码

测试用户注册接口

顺便把用户表中其它用户的密码也加密一下,写个测试用例

自定义认证数据源

springsecurity默认从内存中获取用户信息(
InMemoryUserDetailsManager),现在需要从数据库中查询用户信息,所以需要自定义。

1.定义UserDetails接口的实现类,封装用户信息

获取权限信息的getAuthoities方法留到权限控制一节中完成。

2.定义UserDetailsService接口的实现类,定义获取用户信息的方法

UserDetails接口默认只声明了根据用户名获取用户信息的方法,这里需要支持用户名、手机号、邮箱登录,所以,共定义了3个获取用户信息的方法

实现密码登录

springsecurity默认使用用户名+密码的方式进行登录认证,我们要同时支持用户名、手机号、邮箱3中账号,需要进行自定义。

0.定义2个异常类,代表在手机号码和邮箱不存在异常

1.定义Authentication认证信息存储类

参考
UsernamePasswordAuthenticationToken类,继承抽象类
AbstractAuthenticationToken,负责存储认证以及权限信息

2.定义登录认证Filter

参考
UsernamePasswordAuthenticationFilter类,继承抽象类
AbstractAuthenticationProcessingFilter,负责从请求中获取认证信息,封装为Authentication对象,然后使用AuthenticationManager去进行认证,具体的验证逻辑由AuthenticationProvider负责

3.定义登录认证Provider

参考
AbstractUserDetailsAuthenticationProvider类,实现接口AuthenticationProvider,负责进行具体的认证

4.定义认证成功、认证失败Handler

认证成功处理器实现接口
AuthenticationSuccessHandler

认证失败处理器实现接口
AuthenticationFailureHandler,认证失败抛出的AuthenticationException异常作为参数传入

5.配置

6.测试

分别使用用户名、手机号、邮箱 + 密码进行登录。

登录成功

登录失败: 用户名不存在

登录失败: 账号格式错误

登录失败: 密码错误

实现验证码登录

验证码登录与密码登录差不多,只要把校验密码改为校验验证码即可。

1.定义Authentication认证信息存储类

2.定义登录认证Filter

3.定义登录认证Provider

4.配置

注入Filter和Provider Bean

配置Filter和Provider

5.测试

先获取一下手机验证码,使用手机号+验证码登录

再获取一下邮箱验证码,使用邮箱+验证码登录

实现JWT认证

注意:网上很多教程将登录后的用户信息存储的Redis中,这其实是错误的做法。JWT本身就可以进行信息交换,并且其初衷就用于实现无状态的身份认证,如果使用Redis存储用户信息,本质上是自己又实现了一套Session机制。

采用jwt实现身份认证与信息交换,主要分为2个步骤:

  • 1.客户端请求登录接口,认证通过后,服务端生成jwt令牌,并返回给客户端
  • 2.客户端请求其它需要认证的接口时,携带token,服务端验证token是否有效,以此决定是否放行

0.生成和解析jwt令牌

这里使用开源库jjwt,github:
https://github.com/jwtk/jjwt#install

添加依赖

在application配置文件中,定义2个配置项,并创建响应的Properties类。其中:

  • secret-key表示jwt密钥,使用接下来定义的JWT工具类生成
  • expiration表示令牌过期时间

创建JWT工具类

1.登录成功后,生成jwt令牌并返回给客户端

修改认证成功处理器

测试

2.定义过滤器,验证jwt令牌

3.定义认证异常处理器

实现AuthenticationEntryPoint接口

4.配置

注入Filter Bean

将JWT Filter添加到过滤器链,并配置认证异常处理器

5.测试

访问用户信息接口

不带token时,认证失败

带上token,访问成功

权限控制

基本使用

1.修改自定义的UserDetails类,完善getAuthorities方法

2.定义访问拒绝异常处理器

实现AccessDeniedHandler接口

3.启用全局方法级别的访问控制

也可以在配置类中,使用基于URL资源的访问控制

4.在需要进行权限检查的控制器方法上,声明权限信息

在访问用户列表的控制器方法上,声明管理员权限

5.测试

普通用户访问,失败

管理员访问,成功

相关推荐

Vue 技术栈(全家桶)(vue technology)

Vue技术栈(全家桶)尚硅谷前端研究院第1章:Vue核心Vue简介官网英文官网:https://vuejs.org/中文官网:https://cn.vuejs.org/...

vue 基础- nextTick 的使用场景(vue的nexttick这个方法有什么用)

前言《vue基础》系列是再次回炉vue记的笔记,除了官网那部分知识点外,还会加入自己的一些理解。(里面会有部分和官网相同的文案,有经验的同学择感兴趣的阅读)在开发时,是不是遇到过这样的场景,响应...

vue3 组件初始化流程(vue组件初始化顺序)

学习完成响应式系统后,咋们来看看vue3组件的初始化流程既然是看vue组件的初始化流程,咋们先来创建基本的代码,跑跑流程(在app.vue中写入以下内容,来跑流程)...

vue3优雅的设置element-plus的table自动滚动到底部

场景我是需要在table最后添加一行数据,然后把滚动条滚动到最后。查网上的解决方案都是读取html结构,暴力的去获取,虽能解决问题,但是不喜欢这种打补丁的解决方案,我想着官方应该有相关的定义,于是就去...

Vue3为什么推荐使用ref而不是reactive

为什么推荐使用ref而不是reactivereactive本身具有很大局限性导致使用过程需要额外注意,如果忽视这些问题将对开发造成不小的麻烦;ref更像是vue2时代optionapi的data的替...

9、echarts 在 vue 中怎么引用?(必会)

首先我们初始化一个vue项目,执行vueinitwebpackechart,接着我们进入初始化的项目下。安装echarts,npminstallecharts-S//或...

无所不能,将 Vue 渲染到嵌入式液晶屏

该文章转载自公众号@前端时刻,https://mp.weixin.qq.com/s/WDHW36zhfNFVFVv4jO2vrA前言...

vue-element-admin 增删改查(五)(vue-element-admin怎么用)

此篇幅比较长,涉及到的小知识点也比较多,一定要耐心看完,记住学东西没有耐心可不行!!!一、添加和修改注:添加和编辑用到了同一个组件,也就是此篇文章你能学会如何封装组件及引用组件;第二能学会async和...

最全的 Vue 面试题+详解答案(vue面试题知识点大全)

前言本文整理了...

基于 vue3.0 桌面端朋友圈/登录验证+60s倒计时

今天给大家分享的是Vue3聊天实例中的朋友圈的实现及登录验证和倒计时操作。先上效果图这个是最新开发的vue3.x网页端聊天项目中的朋友圈模块。用到了ElementPlus...

不来看看这些 VUE 的生命周期钩子函数?| 原力计划

作者|huangfuyk责编|王晓曼出品|CSDN博客VUE的生命周期钩子函数:就是指在一个组件从创建到销毁的过程自动执行的函数,包含组件的变化。可以分为:创建、挂载、更新、销毁四个模块...

Vue3.5正式上线,父传子props用法更丝滑简洁

前言Vue3.5在2024-09-03正式上线,目前在Vue官网显最新版本已经是Vue3.5,其中主要包含了几个小改动,我留意到日常最常用的改动就是props了,肯定是用Vue3的人必用的,所以针对性...

Vue 3 生命周期完整指南(vue生命周期及使用)

Vue2和Vue3中的生命周期钩子的工作方式非常相似,我们仍然可以访问相同的钩子,也希望将它们能用于相同的场景。...

救命!这 10 个 Vue3 技巧藏太深了!性能翻倍 + 摸鱼神器全揭秘

前端打工人集合!是不是经常遇到这些崩溃瞬间:Vue3项目越写越卡,组件通信像走迷宫,复杂逻辑写得脑壳疼?别慌!作为在一线摸爬滚打多年的老前端,今天直接甩出10个超实用的Vue3实战技巧,手把...

怎么在 vue 中使用 form 清除校验状态?

在Vue中使用表单验证时,经常需要清除表单的校验状态。下面我将介绍一些方法来清除表单的校验状态。1.使用this.$refs...

取消回复欢迎 发表评论: