jwt 学习笔记
概述
JWT,Java Web Token,通过 JSON 形式作为 Web 应用中的令牌,用于在各方之间安全地将信息作为 JSON 对象传输,在数据传输过程中还可以完成数据加密、签名等相关处理
JWT 的作用如下:
- 授权:一旦用户登录,每个后续请求将包括 JWT,从而允许用户访问该令牌允许的路由,服务和资源
- 信息交换:JSON Web Token 是在各方之间安全地传输信息的好方法,因为可以对 JWT 进行签名,此外,由于签名是使用标头和有效负载计算的,因此还可以验证内容是否篡改
传统的 Session 认证
1. 认证方式

http 协议本身是一种无状态协议,这就意味着如果用户向我们的应用提供了用户名和密码进行认证,那么下次请求时还需再作一次认证。因为根据 http 协议,我们并不知道是哪个用户发出的请求,所以为了让应用能识别是哪个用户发出的请求,我们只能在服务存储一份用户登录的信息,这份登录信息会在响应传递给浏览器,告诉其保存为 cookie,以便下次请求时发送回来,这样我们就能识别请求来自哪个用户了
2. 缺点
- 每个用户经过认证后,都要在服务端做一次记录,以方便下次鉴别。通常而言,session 都是保存在内存中的,随着认证用户的增多,服务端的开销也会明显增大
- 用户认证之后,服务端做认证记录,如果认证的记录被保存到内存中,就意味着下次用户请求还得访问该服务器,才能拿到授权的资源,在分布式应用上,相应的限制了负载均衡器的能力,也就意味着限制了应用的扩展能力
- 基于 cookie 进行用户识别,cookie 一旦被捕获,用户就会很容易受到跨站请求伪造的攻击
- 在前后端分离时增加了部署的复杂性
JWT 认证
1. 认证方式

- 前端通过 Web 表单将自己的用户名和密码发送给后端的接口,这一过程一般是 http post 请求,建议的方式是通过 SSL 加密的传输(https),从而避免敏感信息被嗅探
- 后端核对用户名和密码成功后,将用户的 id 等其他信息作为 JWT Payload(负载),将其与头部分别进行 Base64 编码,拼接后签名,形成一个 JWT Token
- 后端将 JWT 字符串作为登录成功的返回结果返回,前端可以将返回的结果保存在本地缓存上,退出登录时前端删除保存的 JWT 即可
- 前端在每次请求后端带回 JWT
- 后端检查是否存在,如验证 JWT 的有效性,检查签名是否正确,检查 Token 是否过期,检查 Token 接收方是否是自己
- 验证通过后,后端使用 JWT 中包含的用户信息进行其他逻辑操作,返回相应结果
2. 优点
- 简洁,可以通过 URL、POST 参数或者在 HTTP Header 发送,因为数据量小,传输速度快
- 自包含,负载中包含了所有用户需要的信息,避免多次查询数据库
- Token 以加密形式保存在客户端,原则上任何 web 形式都支持
- 不需要在服务端保存会话信息,特别适用于分布式微服务
JWT 结构
通常 JWT 如下所示:xxxxx.yyyyy.zzzzz
标头(Header):标头一般由两部分组成:令牌的类型和所使用的签名算法,标头使用 Base64 编码
{
"alg":"HS256",
"typ":"JWT"
}
有效负载(payload):令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的声明。同样使用 Base64 编码。不建议放入用户的敏感信息
{
"sub":"12345678",
"name":"john",
"admin":true,
...
}
签名(Signature):Signature 需要使用编码后的 Header 和 Payload 以及我们提供的一个密钥,然后使用 Header 中指定签名算法,进行签名。签名的作用是保证 JWT 没有被篡改过,如:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)
客户端收到服务端发送的 token 后,再次请求服务端需要带上 token,此时 token 包含三部分:经过 Base64 编码的 Header、经过 Base64 编码的 Payload 和加密后的签名,服务端用自己保存的 secret 与客户端发送的 Header、Payload 运算,如果结果和客户端带回来的签名不一致,则验证失败
JWT 使用
引入依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
生成 token
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, 20);
Map<String, Object> map = new HashMap<>();
String token = JWT.create().withHeader(map) // header
.withClaim("userId", 21) // payload
.withClaim("username", "yeeq")
.withExpiresAt(instance.getTime()) // 指定令牌的过期时间
.sign(Algorithm.HMAC256("FAWF2#!F@")); // 签名,并指定密钥
根据令牌和签名解析数据
// 创建验证对
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("FAWF2#!F@")).build();
// 解码后的信息
DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDAyNTQ4NzIsInVzZXJJZCI6MjEsInVzZXJuYW1lIjoieWVlcSJ9.jo_6gKThSXUcEfH1e9bu7at9lm2zmdupwiYvMUWopls");
System.out.println(verify.getClaim("userId").asInt());
System.out.println(verify.getClaim("username").asString());
常见异常信息:
SignatureVerificationException:签名不一致异常TokenExpiredException:令牌过期异常AlgorithmMismatchException:算法不匹配异常InvalidClaimException:失效的 payload 异常
JWT 封装工具类
一般结合拦截器或者网关完成认证
public class JWTUtils {
private static final String SIGN = "FAWF2#!F@";
/**
* 生成 token
* @param map payload 的信息
* @return token
*/
public static String getToken(Map<String, String> map) {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE, 7);
JWTCreator.Builder builder = JWT.create();
// 创建 payload
map.forEach((k, v) -> {
builder.withClaim(k, v);
});
String token = builder.withExpiresAt(instance.getTime()) // 指定令牌的过期时间
.sign(Algorithm.HMAC256(SIGN)); // 签名,并指定密钥
return token;
}
/**
* 验证 token 的合法性
* @param token token
*/
public static void verifyJWT(String token) {
JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
}
/**
* 获取 token 的信息
* @return token 的信息
*/
public static DecodedJWT getTokenInfo(String token) {
DecodedJWT verify = JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
return verify;
}
}
jwt 学习笔记的更多相关文章
- golang学习笔记10 beego api 用jwt验证auth2 token 获取解码信息
golang学习笔记10 beego api 用jwt验证auth2 token 获取解码信息 Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放 ...
- golang学习笔记7 使用beego swagger 实现API自动化文档
golang学习笔记7 使用beego swagger 实现API自动化文档 API 自动化文档 - beego: 简约 & 强大并存的 Go 应用框架https://beego.me/doc ...
- 【原创】SpringBoot & SpringCloud 快速入门学习笔记(完整示例)
[原创]SpringBoot & SpringCloud 快速入门学习笔记(完整示例) 1月前在系统的学习SpringBoot和SpringCloud,同时整理了快速入门示例,方便能针对每个知 ...
- Spring Security + JWT学习
开胃:Oauth2认证流程分析 现在第三方登录已经很普遍了,随便哪个App都会有使用微信登录,使用手机号码登录,或者使用支付宝登录等功能... 下面我们就以使用微信登录,做一个简单的流程分析分析 开胃 ...
- SpringBoot学习笔记(十五:OAuth2 )
@ 目录 一.OAuth 简介 1.什么是OAuth 2.OAuth 角色 3.OAuth 授权流程 4.OAuth授权模式 4.1.授权码 4.2.隐藏式 4.3.密码式 4.4.凭证式 二.实践 ...
- 图灵学院JAVA互联网架构师专题学习笔记
图灵学院JAVA互联网架构师专题学习笔记 下载链接:链接: https://pan.baidu.com/s/1xbxDzmnQudnYtMt5Ce1ONQ 密码: fbdj如果失效联系v:itit11 ...
- Spring Cloud微服务学习笔记
Spring Cloud微服务学习笔记 SOA->Dubbo 微服务架构->Spring Cloud提供了一个一站式的微服务解决方案 第一部分 微服务架构 1 互联网应用架构发展 那些迫使 ...
- SpringBoot + Security学习笔记
SpringSecurity学习笔记 本以为是总结,最后写成了笔记,所以还是需要更加的努力啊. 开始的时候看了一遍官方文档,然后只看懂了加密器. 然后又学了一个尚硅谷的视频,虽然这个教程是在讲一个项目 ...
- Vue学习笔记-rest_framework_jwt 学习
一 使用环境 开发系统: windows 后端IDE: PyCharm 前端IDE: VSCode 数据库: msyql,navicat 编程语言: python3.7 (Windows x86- ...
- Vue学习笔记-Django REST framework3后端接口API学习
一 使用环境 开发系统: windows 后端IDE: PyCharm 前端IDE: VSCode 数据库: msyql,navicat 编程语言: python3.7 (Windows x86- ...
随机推荐
- 2022-07-11 第一小组 张明旭 前端JS学习记录
今天是正式学习的第三天,每天一大部分前端的新知识,吐瘦两斤,听课晕乎乎的.不过小事,靠笔记和视频苟活 知识点: JavaScript是什么? 编程语言.脚本语言.依赖于某种容器(浏览器)运行 有浏览器 ...
- Opengl数学markdown
# opengl数学 $$\begin{Bmatrix} {A_{x}}\\ {A_{y}}\\ {A_{z}}\\ \end{Bmatrix} * \begin{Bmatrix} {B_{x}}\\ ...
- FATAL Exited too quickly (process log may have details)的解决方案
作为一个混混的开发,不会啥容器操作.所以一般都是用supervisor来管理一些运行的进程 用了一段时间还是比较好用的,这个软件也是用的Python开发. 但在使用的过程中,status时会出现 FA ...
- 【APT】Hades APT组织针对乌克兰发起网络攻击事件分析
背景 Hades一个充满神秘色彩的APT组织,该组织因为2017年12月22日针对韩国平昌冬奥会的攻击活动被首次发现,后来卡巴斯基将该次事件的攻击组织命名为Hades.但是该攻击组织的归属问题却一直未 ...
- 记录一次 网关负载 流量不均匀 cpu使用率不均衡问题
网关负载 流量不均匀 cpu使用率不均衡问题??? 1.压力机访问源 有多少ip 有10个? 还是20个? 就是样本源不多的话,负载上hash的话 就你可能不是真实的访问需求 ,你客户端就那么 ...
- MySQL innodb存储引擎的数据存储结构
InnoDB存储引擎的数据存储结构 B+ 树 为什么选择B+树? 因为B+树的叶子节点存储了所有的data,所以它的非叶子节点可以存储更多的key,使得树更矮:树的高度几乎就是I/O的次数,所以选择更 ...
- 【PyQt6】Python使用QtCharts画图修改背景色的问题
问题 想在软件界面用PyQt6的QtChart新画一张饼图,自定义一个饼图类继承QChartView: class PyPieChart(QChartView): def __init__( self ...
- echarts区域选择(brush)默认开启选择
api.dispatchAction({ // 刷选模式的开关.使用此 action 可将当前鼠标变为可刷选状态. 事实上,点击 toolbox 中的 brush 按钮时,就是通过这个 action, ...
- GVINS文章暴力翻译(仅供自学)
https://blog.csdn.net/haner27/article/details/117929327
- Unity 安装的编辑器版本不见了 记录问题
新的一天打开unity 报错,然后再打开就找不到我之前安装的编辑器版本了 (猜测是我不正常关闭的原因吧,不懂这个) 之前在网上找到过解决办法,后来找不到了.趁现在还记得,记录一下 先把进程停了 再把缓 ...