spring boot jwt_SpringBoot+SpringSecurity基于JWT的身份认证和角色授权

f852f104611311384897f5e657da0425.png

在前面的文章中,我们已经使用 token 实现前后端分离的系统登录及访问鉴权。

第二十四章:整合SpringSecurity之最简登录及方法鉴权

第二十五章:整合SpringSecurity之使用数据库实现登录鉴权

第二十六章:整合SpringSecurity之JSON格式前后端交互

第二十七章:整合SpringSecurity之前后端分离使用Token实现登录鉴权

登录成功后,服务端会生成一个 token 并存储起来,这样客户端携 token 再次访问时,服务端就可以根据 token 获取当前用户的登录状态及用户信息。在之前的示例中,我们将 token 存储在数据库中,客户端每次访问都需要从数据库中读取 token 相关联的用户信息。数据库通常是系统的性能瓶颈,每次请求都需要先访问数据库,对数据库来说压力山大。

当然,我们使用 Redis 之类的高性能中间件来存储 token,这样相对来说,压力来会减少,但是压力依然在。那么有没有一种技术,在服务端获取到 token 之后,可以直接根据 token 解析出用户信息,这样就可以避免从存储中间件获取信息给系统造成的压力。

JWT(Java Web Token)就是这样的一种技术。

相关知识

什么是 JWT

请参考阮一峰博客 http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html,里面有比较详尽的介绍。

目标

整合 SpringSecurity 实现使用 JWT 进行登录及访问鉴权。

准备工作

创建用户表 user、角色表 role、用户角色关系表 user_role,因为 JWT 本身就是用户信息,所以不用再另行存储,可以直接解析

d3c72ef3d15e7ad62b4faba41138fe02.png

操作步骤

添加依赖

引入 Spring Boot Starter 父工程

5a5b5fcd4a8717571b808453a85946f4.png

添加 springSecurity 及 mybatisPlus 的依赖,添加后的整体依赖如下

47aee52f8963c8161e86ef2e905fd002.png

配置

配置一下数据源

9bfc61bca449fd507c601fff89e388af.png

编码

实体类

角色实体类 Role,实现权限接口 GrantedAuthority

44f68f7d36c39cdb0ccc624d801b7f62.png

用户实体类 user,实现权限接口 UserDetails,主要方法是 getAuthorities,用于获取用户的角色列表

1505a0f12ef0878b04af89483e6d27b4.png

用户角色关系实体

109776746aaed92022086577f715fda0.png

Repository 层

分别为三个实体类添加 Mapper

884e0354de93808bed117260d69b8671.png

实现 UserDetailsService 接口

UserDetailsService 是 SpringSecurity 提供的登陆时用于根据用户名获取用户信息的接口

94fb38b541e5fdf1f8d176446c484925.png

自定义登录参数格式

7656751ce6452d8a3f4d76040f6f05f0.png

自定义登录过滤器

继承 SpringSecurity 提供的 AbstractAuthenticationProcessingFilter 类,实现 attemptAuthentication 方法,用于登录校验。

本例中,模拟前端使用 json 格式传递参数,所以通过 objectMapper.readValue 的方式从流中获取入参,之后借用了用户名密码登录的校验,

如果鉴权成功,使用 JWT 工具类生成 token 并将 token 返回给前端。

c2c83c0c01f1fe6ec614d2d1903d603e.png

自定义登陆成功后处理

实现 SpringSecurity 提供的 AuthenticationSuccessHandler 接口,使用 JSON 格式返回

87cfab35d62ad23edc20ba30ad708302.png

自定义登陆失败后处理

实现 SpringSecurity 提供的 AuthenticationFailureHandler 接口,使用 JSON 格式返回

5e843d24494a80bf78b5f91665e6127c.png

自定义权限校验失败后处理

登陆成功之后,访问接口之前 SpringSecurity 会进行鉴权,如果没有访问权限,需要对返回进行处理。实现 SpringSecurity 提供的 AccessDeniedHandler 接口,使用 JSON 格式返回

91a16054ca0ebe087a6dbd7ce708b1a2.png

自定义未登录后处理

实现 SpringSecurity 提供的 AuthenticationEntryPoint 接口,使用 JSON 格式返回

20305672182b1fc88bd442e59b07fb2c.png

自定义 Token 验证过滤器

客户端登录成功时,后台会把生成的 token 返回给前端,之后客户端每次请求后台接口将会把这个 token 附在 header 头中传递给后台,后台会使用 JWT 工具类进行验证这个 token 是否有效,并把 JWT 中包含的信息解析成用户对象,加载至 SpringSecurity 中。

b22c9ff65876b4ca06652440fa4ea6bb.png

JWT 工具类

2cbf1ba52674e365230648d5cf90ce4f.png

注册

在 configure 方法中将自定义的 jsonAuthenticationFilter 及 tokenAuthenticationFilter 注册进 SpringSecurity 的过滤器链中,并禁用 session。

4cdfc7a7c47a3109a2ba3737f88a361b.png

启动类

ea0c24f105b96d34ee5441978d45a2c0.png

验证结果

初始化数据

7de95d7eb86450254ad0d4326e81e8f7.png

源码地址

本章源码 : https://gitee.com/gongm_24/spring-boot-tutorial.git

结束语

与普通的 token 不同的是,JWT 作为 token 本身就已经包含了信息,而普通的 token 就只是一个字符串,需要用户信息就必须再去数据库或者其它中间件中进行加载,JWT 则可以省去这一步,这可以大幅度降低系统的 IO。

但是 JWT 也有自己的问题,那就是一旦生成,服务端将无法控制它,只要在有效期内就可以一直使用,所以 JWT 更适用于短期授权。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值