前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot项目集成用户身份认证(上)深入理解Session、Token、JWT

SpringBoot项目集成用户身份认证(上)深入理解Session、Token、JWT

作者头像
天罡gg
修改2023-04-02 15:48:30
1.9K0
修改2023-04-02 15:48:30
举报
文章被收录于专栏:天罡gg天罡gg

前言

在上文,我们实现了基于SpringBoot项目的API接口开发,并实现 API结果统一封装、支持跨域请求等等功能,接下来做的是开发登录接口,实现一套统一鉴权的用户身份认证的机制

我已经提前和狗哥一起讨论确定了认证机制,会采用目前流行的基于JWT的Token用户身份认证机制,主流程如下:

  1. 前端请求【用户名+密码登录】接口,后端验证通过后生成Token 返回给前端;
  2. 前端保存Token,以后每次请求API都会携带Token,后端校验Token通过就正常返回数据;
  3. 直到后端校验Token已失效,这时再从第1步重新开始。
JWT认证流程
JWT认证流程

为什么这么选型?我们都考虑了哪些点?是不是拍脑袋来的?

我希望你能有这些疑问,而不仅仅是被动的接收,主动思考=真正的理解!

OK,那我也很乐意和大家一起探讨:怎么做好用户身份认证!

所以,在实战写代码之前,我们有必要深入理解Session、Token、JWT,都是什么?都有什么优缺点?

同时,希望通过本文,大家能对Session、Token、JWT有深入透彻的理解,相信本文一定会让你有所收获!

PS,完整的用户身份认证代码早已实现,和狗哥也已联调通过,正在赶工博文,预告一下我将分三篇来写,非常详细,料很足,准备好发车喽,Let’s go!

  • (上)深入理解Session、Token、JWT
深入理解Session、Token、JWT
深入理解Session、Token、JWT
  • (中)实战基于JWT生成和校验Token
实战基于JWT生成和校验Token
实战基于JWT生成和校验Token
  • (下)实战基于JWT+双重检查的登录+登出+拦截器 --防XSS+CSRF漏洞
实战基于JWT+双重检查的登录+登出+拦截器 --防XSS+CSRF漏洞
实战基于JWT+双重检查的登录+登出+拦截器 --防XSS+CSRF漏洞

专栏介绍

因为可能还有很多同学还不清楚上下文,所以简单介绍一下这个专栏要做的事:

天罡老哥和狗哥(博客主页)有意从0到1带大家搭建一个SpringBoot+SpringCloud+Vue的前后端分离项目! 打造一个短小精悍、技术主流、架构规范的前后端分离实战项目!我负责后端,狗哥负责前端! 目的就是让大家通过项目实战,学到一些真东西,将所学理论落地,助力有心强大的你更快的成长!开启你的工作之旅,让开发游刃有余!

详细的后端规划后端大纲思维导图开篇已经给出,专栏的总进度如下:

SpringBoot+Vue前后端分离项目实战 - 服务端部分

1. 基于SpringBoot+SpringCloud+Vue前后端分离项目实战 --开篇

2. 天狗实战SpringBoot+Vue(一)环境安装

3. 天狗实战SpringBoot+Vue(二)项目结构搭建(上)

4. 天狗实战(二)SpringBoot API开发详解 --SpringMVC注解+封装结果+支持跨域+打包(下)

5. Maven依赖加载不进来? 依赖加载失败? 你值得掌握如何排查的方法

6. 实战Git常用操作(IDEA界面+命令):初始化(init)、忽略文件(.gitignore)、提交(commit)、查看提交记录(log)、创建+切换分支(branch)

Vue + SpringBoot前后端分离项目实战 - 前端部分

1. 手把手带你做一套毕业设计-征程开启

2. 我应该把毕业设计做到什么程度才能过关?

3. 做毕业设计,前端部分你需要掌握的6个核心技能

4. 基于Vue+Vue-cli+webpack搭建渐进式高可维护性前端实战项目

5. 基于Vue+Less+axios封装+ElementUI搭建项目底层支撑实战

6. 使用Vue+vue-router+路由守卫实现路由鉴权功能实战


提前说明: 因为HTTP 是无状态的协议,每个请求都是完全独立的,服务端无法确认当前访问者的身份信息,无法分辨上一次的请求发送者和这一次的发送者是不是同一个人,所以就需要在用户登录后进行登录态的管理

一、基于Cookie的Session(会话)认证机制

其中有一种是基于Session的方式,是一种记录服务端和浏览器会话状态的机制,大致的流程如下:

  1. 登录成功后,服务端根据用户信息生成唯一标识SessionId ,比如根据用户ID+加随机盐salt,然后进行各种加密生成
  2. 服务端保存SessionId以及对应的用户信息,比如保存在内存或Redis等,需要维护过期时间。然后将SessionId写入Cookie。
  3. 前端请求API时会自动携带Cookie中的SessionId,服务端通过SessionId获取Session进行校验:
    • 如果找到 Session 证明用户已经登录,进行后续处理;
    • 如果未找到Session说明用户没有登录或者登录失效,这时再从第1步重新开始。
基于Cookie的Session(会话)认证机制
基于Cookie的Session(会话)认证机制

好处:

  1. 因为SessionId保存在Cookie,会自动携带,所以对Web前端来说不需要维护SessionId,非常方便。

缺点:

  1. 存在安全问题,因为Cookie自动携带,存在被黑客使用【CSRF跨站请求伪造】攻击的漏洞
  2. Cookie无法跨域
  3. 移动端对Cookie的支持不是很友好
  4. 服务端需要存储Session,维护过期时间,占用服务器资源,在分布式应用中还需要维护Session同步,另外校验时需要读取Session

二、基于Token(令牌)认证机制

基于Token的认证方式,又分为两种:

1. 有状态的Token

有状态的Token方式,服务端需要保存Token数据

比如, 将基于Cookie的Session方式变一变,不基于Cookie了,而是由前端自行维护Token,大致的流程如下:

  1. 登录成功后,服务端根据用户信息生成唯一标识TokenId ,比如根据用户ID+加随机盐salt,然后进行各种加密生成
  2. 服务端保存TokenId以及对应的用户信息,比如保存在内存或Redis等,需要维护过期时间。然后将TokenId返回给前端。
  3. 因为不基于Cookie,所以前端需要自行保存TokenId,比如保存在localStorage等,请求API时控制携带TokenId,服务端通过TokenId去内存或Redis搜索匹配的Token:
    • 如果找到Token,证明用户已经登录,进行后续处理;
    • 如果未找到Token,说明用户没有登录或者登录失效,这时再从第1步重新开始。
基于有状态Token(令牌)认证机制
基于有状态Token(令牌)认证机制

当Token不需要保存除用户ID之外的信息时,Token就等于TokenId,只是保存的信息变少,但仍然需要服务端保存,例如保存在内存中的话就是数据结构用Map还是Set的区别,或者Map的value是不是空的区别。

好处:

  1. 因为Token完全由前端维护,不基于Cookie,所以可以避免CSRF攻击、支持跨域、对移动端友好。

缺点:

  1. 和Session方式有同样的缺点:服务端需要存储Token,维护过期时间,占用服务器资源,在分布式应用中还需要维护Token同步,另外校验时需要读取Token

当然还有其它场景:

  • 比如,你申请调用第三方平台的接口,它会为你生成一个一直有效的Token,那么这个Token就是保存在第三方的服务端,也是有状态的。
  • 再比如,你可能听说过refresh_token,用于刷新access_token,access_token可以不用在服务端保存,但refresh_token还需要保存在服务端,这些都可以称为有状态的。

2. 无状态的Token

无状态的Token方式,服务端不用保存Token数据,是不是听上去很历害?大致的流程如下:

  1. 登录成功后,服务端生成Token 返回给前端;
  2. 前端保存Token,比如保存在localStorage等,请求API时控制携带Token,服务端接收后校验Token
    • 校验Token通过,进行后续处理;
    • 校验Token不通过,说明用户没有登录或者登录失效,这时再从第1步重新开始。
基于无状态Token(令牌)认证机制
基于无状态Token(令牌)认证机制

好处:

  1. 因为Token完全由前端维护,不基于Cookie,所以可以避免CSRF攻击、支持跨域、对移动端友好。
  2. 服务端不需要维护Token,节省了服务器资源,在分布式应用中更多省去了很多麻烦

缺点:

  1. 也正是因为服务端没有保存Token,引申出来Token无法主动过期的问题。颁发后在过期时间内就会一直有效,所以在主动登出时需要处理如何让Token主动失效。

三、JWT

JWT (JSON Web Token) 是一种开放标准(RFC 7519)定义的JSON对象,本质是一个字符串,正是无状态Token中的一种。那它是如何做到不用服务端保存,仅通过自身就能完成校验?

这和人民币防伪有点类似,是因为它本身既包含用户信息等数据,也包含过期时间数字签名,虽然数据经过传输,但接收方仍可以直接校验它是否过期是否被篡改

还没理解?那我们看一下它的组成:

JWT组成
JWT组成

如上图右侧是解码后的数据,左侧JWT字符串,由图中3种颜色代表的3个部分组成(以逗号连接):

1Header.2Payload.3Signature

1. Header

元数据,定义了生成签名的算法以及 Token 的类型。

代码语言:javascript
复制
{
  "typ": "JWT",
  "alg": "RS256"
}
  • typ:表示Token类型,JWT统一为JWT
  • alg:表示签名算法,像RS256、HS256

2. Payload

载荷,是传递数据的载体,包含7个内置字段:

代码语言:javascript
复制
String ISSUER = "iss"; 		// 发行人
String SUBJECT = "sub"; 	// 主题
String EXPIRES_AT = "exp"; 	// 失效时间
String NOT_BEFORE = "nbf"; 	// 在此之前不可用
String ISSUED_AT = "iat"; 	// 发布时间
String JWT_ID = "jti"; 		// JWT id值
String AUDIENCE = "aud"; 	// 用户

重点是 exp 失效时间 ,其它可选使用,例如:我可以将 iss 指定保存userId

用户信息就保存在这里,上面7个不够的话,还可以自定义字段,例如:我自定义了userName:

代码语言:javascript
复制
{
  "sub": "TgAuthSSO",
  "nbf": 1679984611,
  "iss": "1",
  "exp": 1679984911,
  "userName": "张三",
  "iat": 1679984611
}

注意:payload中数据默认未加密,所以不适合放隐私信息字段,比如用户的密码等,防止信息泄露。

3. Signature

签名,这是JWT防止内容被篡改的关键!

通过使用 Header 里面指定的签名算法,对Payload和Header加密而生成。


四、为什么选择JWT?

1. 安全

数据被签名加密后,可以有效防止内容被篡改。

例如:RSA算法,目前仍是非常可靠的加密算法,极难破解!

2. 无状态

【无状态】是相对【有状态】而言,【有状态】是指服务器端需要保存数据。

JWT由于其自带校验的所有数据,本身就可以验证Token是否被篡改、是否合法、是否过期,所以不需要在服务器存储Token,对于分布式场景省去了很多麻烦,更主要的是节省了服务器资源!

3. 可自定义字段

能够在Payload中自定义存储字段,保证了扩展性,可以把常用数据写进去,避免数据的二次读取。


本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 专栏介绍
  • 一、基于Cookie的Session(会话)认证机制
    • 好处:
      • 缺点:
      • 二、基于Token(令牌)认证机制
        • 1. 有状态的Token
          • 好处:
          • 缺点:
        • 2. 无状态的Token
          • 好处:
          • 缺点:
      • 三、JWT
        • 1. Header
          • 2. Payload
            • 3. Signature
            • 四、为什么选择JWT?
              • 1. 安全
                • 2. 无状态
                  • 3. 可自定义字段
                  相关产品与服务
                  云数据库 Redis
                  腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档