JWT (JSON Web Token) 是目前最流行的跨域认证解决方案,是一种基于 Token 的认证授权机制。
从 JWT 的全称可以看出,JWT 本身也是 Token,一种规范化之后的 JSON 结构的 Token。
通过数字签名的方式,以 JSON 对象为载体,在不同的服务终端之间安全的传输信息。
JWT 自身包含了身份验证所需要的所有信息,因此,我们的服务器不需要存储 Session 信息。这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力。(JWT 存储在【客户端】)
并且,使用 JWT 认证可以有效避免 CSRF 攻击,因为 JWT 一般是存在在 localStorage 中,使用 JWT 进行身份验证的过程中是不会涉及到 Cookie 的。
JWT 最常见的场景就是授权认证,一旦用户登录,后续每个请求都将包含 JWT,系统在每次处理用户请求的之前,都要先进行 JWT 安全校验,通过之后再进行处理。
JWT 由 3 部分组成,用 .
拼接
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJ1c2VybmFtZSI6IlRvbSIsInJvbGUiOiJhZG1pbiIsInN1YiI6ImFkbWluLXRlc3QiLCJleHAiOjE2MjMyMjM2NzUsImp0aSI6ImQ2MTJjZjcxLWI5ZmUtNGMwNy04MzQwLTViOWViZmMyNjExNyJ9
.FOS9Y7rYNdc2AOidnSPrgg2XTYePU0yGZ598h2gtabE
可以在 jwt.io 这个网站上对 JWT 进行解码,解码之后得到的就是 Header、Payload、Signature 这三部分。
这三部分分别是:
Header 通常由两部分组成:
typ
(Type):令牌类型,也就是 JWT。alg
(Algorithm):签名算法,比如 HS256。JSON 形式的 Header 被转换成 Base64 编码,成为 JWT 的第一部分。
{
'typ': 'JWT',
'alg': 'HS256'
}
Payload 也是 JSON 格式数据,其中包含了 Claims(声明,包含 JWT 的相关信息)。
Payload 部分默认是不加密的,一定不要将隐私信息存放在 Payload 当中!!!
JSON 形式的 Payload 被转换成 Base64 编码,成为 JWT 的第二部分
Claims 分为三种类型:
下面是一些常见的注册声明:
iss
(issuer):JWT 签发方。iat
(issued at time):JWT 签发时间。sub
(subject):JWT 主题。aud
(audience):JWT 接收方。exp
(expiration time):JWT 的过期时间。nbf
(not before time):JWT 生效时间,早于该定义的时间的 JWT 不能被接受处理。jti
(JWT ID):JWT 唯一标识。{
"uid": "ff1212f5-d8d1-4496-bf41-d2dda73de19a",
"sub": "1234567890",
"name": "John Doe",
"exp": 15323232,
"iat": 1516239022,
"scope": ["admin", "user"]
}
{
"sub": '1234567890',
"name": 'john',
"admin": true
}
Signature 部分是对前两部分的签名,作用是防止 JWT(主要是 payload)被篡改。
这个签名的生成需要用到:
secret
HMACSHA256
// 第一种方式
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'secret');
// 第二种方式
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(
.
)分隔,这个字符串就是 JWT 。
pom.xml
文件
<dependency>
<groupId>io.jsonwebtokengroupId>
<artifactId>jjwtartifactId>
<version>0.9.1version>
dependency>
<dependency>
<groupId>javax.xml.bindgroupId>
<artifactId>jaxb-apiartifactId>
<version>2.3.0version>
dependency>
<dependency>
<groupId>com.sun.xml.bindgroupId>
<artifactId>jaxb-implartifactId>
<version>2.3.0version>
dependency>
<dependency>
<groupId>com.sun.xml.bindgroupId>
<artifactId>jaxb-coreartifactId>
<version>2.3.0version>
dependency>
<dependency>
<groupId>javax.activationgroupId>
<artifactId>activationartifactId>
<version>1.1.1version>
dependency>
也可用 Hutool 中的工具类生成 JWT 来进行食用:JWT工具-JWTUtil (hutool.cn)
在基于 JWT 进行身份验证的的应用程序中,
服务器通过 Payload、Header 和 Secret(密钥)创建 JWT 并将 JWT 发送给客户端。
客户端接收到 JWT 之后,会将其保存在 Cookie 或者 localStorage 里面,以后客户端发出的所有请求都会携带这个令牌。
从用户的角度来分析:
JWT (JSON Web Token) 被用于代替传统的基于 Session 的身份认证和授权机制的主要原因有以下几点:
总的来说,JWT 是一种轻量级、可扩展、无状态和安全的认证机制,相较于传统的基于 Session 的认证机制,JWT 具有更多优势,特别适合于现代的分布式、跨域和无状态的应用场景。
store
)1、前端在用户登录之后保存登录信息
// 变量提交:保存登录信息, 即 token
store.commit("setMember", data.content);
2、修改 axios 全局拦截器
为请求 headers 增加 token,并返回配置
axios.interceptors.request.use(function (config) {
console.log('请求参数:', config);
const _token = store.state.member.token;
if (_token) {
config.headers.token = _token;
console.log("请求headers增加token:", _token);
}
return config;
}, error => {
return Promise.reject(error);
});
Hutool 对 JWT 的介绍:概述 (hutool.cn)
存在的问题分析:
token 被解密
token 被拿到第三方使用
简单来说就是: 自己的产品,被别人包了一个界面,做成他们收费的产品。(比如 ChatGPT 聊天机器人,外表包装成一个小程序,实际上是利用开发者设置的 token 去官网请求信息)
没啥好办法,只能使用限流(检测流量大的情况)