理解并剖析JWT的身份验证流程及其安全特性
(一)讲一下jwt 鉴权原理
JWT(JSON Web Token)是一种基于标准JSON格式的轻量级身份认证和授权协议。JWT由三部分组成:Header(头部)、Payload(载荷)和Signature(签名)。下面简要介绍JWT的使用过程:
-
用户通过用户名和密码向服务器发送登录请求。
-
服务器收到请求后,验证用户名和密码是否正确。如果验证通过,服务器将用户信息作为Payload(载荷)加入到JWT中,并设置过期时间等信息,然后使用加密算法生成Signature(签名)。
-
服务器将Header(头部)、Payload(载荷)和Signature(签名)三个部分组合成JWT,并把JWT返回给客户端。
-
客户端收到JWT后,将其保存在本地(一般存储在localStorage或Cookie中)。
-
在后续的请求中,客户端将JWT加入到Authorization的请求头中并发送请求,如"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"。
-
服务器接收请求后,从Authorization头中获取JWT,并验证其合法性以及过期时间等信息。
-
如果JWT验证通过,则返回所请求的数据或服务;如果验证失败,则返回错误提示等信息。
总体来说,JWT的使用过程分为三个阶段:登录认证阶段、JWT传递阶段和鉴权阶段。在登录认证阶段,服务器将用户信息加密生成JWT并返回给客户端;在JWT传递阶段,客户端将JWT保存并在后续请求时加入Authorization头中传递给服务器;在鉴权阶段,服务器获取JWT并进行验证,若验证通过则返回请求的服务或数据,否则返回错误信息,从而实现了身份认证和授权。
代码案例
前端
在前端,需要将生成的Token存储下来,并在发起请求时将Token放在请求头或参数中进行传递。
以放在请求头中为例,可以使用Axios库来实现:
import Axios from "axios";
//获取存储在localStorage中的Token
let token = window.localStorage.getItem("token");
//设置请求头
// Bearer 是一种身份验证协议(即 Token 传递的一种格式),在 JWT 中也是常用的身份验证方式之一。
Axios.defaults.headers.common["Authorization"] = "Bearer " + token;
//发起请求
Axios.get("/api/user").then(res => {
console.log(res.data);
}).catch(err => {
console.log(err);
});
以上代码中,我们使用Axios设置了请求头并发起了GET请求,其中"/api/user"为示例接口地址,需要根据实际情况进行修改。同时也需要注意,前端存储Token的方式有多种,可以使用Cookie或者localStorage等进行存储。
后端
以下是基于Node.js、Express框架开发的JWT案例。
首先,在项目中需要安装jsonwebtoken库,用于生成和验证Token。
步骤一:生成Token
const jwt = require("jsonwebtoken");
//用户信息,可以是用户名、用户ID等
let user = {name: "somebody", age: 18};
//密钥,可自定义
let secretKey = "my_secret_key";
//生成Token
let token = jwt.sign(user, secretKey, {expiresIn: "1h"});
//expiresIn表示token有效期,"1h"表示1小时
console.log(token);
步骤二:验证Token
//获取前端传递的Token值
let token = req.headers.authorization.split(" ")[1];
//密钥,可自定义
let secretKey = "my_secret_key";
//验证Token
try {
let decoded = jwt.verify(token, secretKey);
console.log(decoded);
//Token验证成功
} catch (err) {
console.log(err);
//Token验证失败
}
以上代码可以实现Token的生成和验证,作为身份验证的一种方式,在项目中得到了广泛应用。
(二)jwt 的安全性
JWT具有以下安全性优势:
-
无状态:JWT本质上是一个Token,它将用户信息、授权等信息封装在了Payload中,因此JWT不需要在服务端保存会话信息,即它是无状态的。这使得JWT能够轻松地用于分布式系统。
-
加密签名:JWT有一个Signature(签名)部分,使用一定的加密算法对Header(头部)和Payload(载荷)进行签名。因此,在服务器端对JWT进行验证的同时,必须检查JWT的签名是否正确,以确保Token没有被篡改过。
-
可扩展性:JWT并不限制其Payload里存储的信息类型,所以我们可以用JWT来在应用之间安全地传输各种信息,如用户ID、角色、权限等。
-
过期时间:JWT中可以设置过期时间,一旦Token过期,就需要重新登录获取新的Token。这使得Token只有在有效期内才能够使用。
尽管JWT具有这些优势,但是在使用时也需要注意以下安全问题:
-
加密算法的选择:选择安全可靠的加密算法对数据进行加密和签名,如RS256或HS256等。
-
Token的管理:Token在客户端是存储在localStorage或Cookie中,因此可能面临一些安全风险,如XSS攻击或CSRF攻击等。所以,需要保证Token加密和存储的安全性,并设置合理的过期时间。
-
范围控制:在授权用户时,需要确保JWT中存储的信息与用户所请求的URL或服务匹配,以防止恶意用户利用JWT访问未授权的资源。
总的来说,JWT使用方便且安全可靠,但也需要注意使用场合以及安全隐患,并采取相应的措施来提高安全性。
如何保证token的安全
-
使用加密算法再对token加一次密,一种可行的方式是使用对称加密算法,如 AES,使用一个密钥对 Token 进行加密和解密。
-
存储在HttpOnly Cookie 上,HttpOnly Cookie 禁止 JavaScript 访问 Cookie。可以有效防范xss攻击,但不能完全防范。为了更好地保护 Web 应用程序,需要采取多种安全措施,如输入验证、输出编码和身份验证等。
-
使用 HTTPS 协议传输数据,以保障数据传输的安全性。
-
通过设置短暂有效期来减少 JWT token 被盗用的风险。
-
将 JWT token 存储在 HttpOnly Cookie 中,以防止 XSS 攻击窃取 JWT token。
-
使用签名来验证 JWT token 的完整性,以防止攻击者篡改 JWT token。
-
避免在 JWT token 中包含敏感信息,例如用户的密码。
-
使用多因素身份验证等措施来提高账户的安全性。