什么是 JWT?
JWT,全称为 JSON Web Token,是一种用于客户端与服务端安全通信的开放标准(RFC 7519)。JWT 的主要用途是 身份验证 和 信息交换。它以紧凑、安全的方式,将信息封装成 JSON 对象,方便传输和验证。
JWT 的组成
一个完整的 JWT 是一个由三部分组成的字符串,每部分用 . 分隔:
css
复制代码
Header.Payload.Signature
-
Header(头部) : 头部定义了令牌的类型和签名算法,例如:
json 复制代码 { "alg": "HS256", "typ": "JWT" }经过 Base64 编码后会变成类似:
复制代码 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 -
Payload(载荷) : 载荷是实际存储信息的地方,通常包含用户身份信息(
sub)和过期时间(exp)。例如:json 复制代码 { "sub": "1234567890", "name": "John Doe", "admin": true, "exp": 1716239022 }编码后为:
复制代码 eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9 -
Signature(签名) : 签名用于验证令牌的完整性。由以下公式生成:
scss 复制代码 HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)生成的签名类似:
复制代码 SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
完整的 JWT 为:
复制代码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWT 的优点
- 轻量级:基于 JSON 格式,大小较小,易于传输。
- 跨平台:无论客户端是 Web、移动端还是其他平台,都可以轻松使用。
- 安全性:签名防篡改,私密信息仅在服务端解密。
- 无状态:令牌包含了全部用户信息,无需在服务端存储会话数据。
JWT 的常见应用场景
-
身份认证:
- 用户登录成功后,服务端生成 JWT 并返回给客户端。
- 客户端在每次请求时附加 JWT 到
Authorization头。 - 服务端验证 JWT 并授予或拒绝访问。
-
信息交换:
- 不同系统间安全传递认证信息。
-
单点登录(SSO) :
- JWT 的无状态特性非常适合实现单点登录。
JWT 使用示例
安装依赖
使用 Python 的 Flask 框架实现 JWT 功能,先安装必要的库:
bash
复制代码
pip install flask flask-jwt-extended
创建项目文件
创建一个名为 app.py 的文件,输入以下代码:
python
复制代码
from flask import Flask, jsonify, request
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity
app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'your_secret_key' # 设置密钥
jwt = JWTManager(app)
# 用户登录,返回 JWT
@app.route('/login', methods=['POST'])
def login():
username = request.json.get('username', None)
password = request.json.get('password', None)
# 简单的用户验证逻辑
if username != 'admin' or password != 'password':
return jsonify({"msg": "Bad username or password"}), 401
# 生成 JWT
access_token = create_access_token(identity=username)
return jsonify(access_token=access_token)
# 受保护的路由,需要 JWT 验证
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
current_user = get_jwt_identity()
return jsonify(logged_in_as=current_user), 200
if __name__ == '__main__':
app.run(debug=True)
代码解析
-
配置 JWT 密钥:
JWT_SECRET_KEY是用来签名令牌的密钥,必须保密。
-
生成令牌:
- 使用
create_access_token函数创建令牌,identity参数用来存储用户标识信息。
- 使用
-
验证令牌:
- 在受保护的路由中,使用
@jwt_required()装饰器验证请求中的 JWT。 - 如果验证成功,可以通过
get_jwt_identity()获取当前用户信息。
- 在受保护的路由中,使用
运行项目
在终端运行以下命令:
bash
复制代码
python app.py
使用工具(如 Postman)测试以下流程:
-
登录获取 JWT:
-
POST 请求:
http://127.0.0.1:5000/login -
请求体:
json 复制代码 { "username": "admin", "password": "password" } -
响应:
json 复制代码 { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }
-
-
访问受保护资源:
-
GET 请求:
http://127.0.0.1:5000/protected -
请求头:
makefile 复制代码 Authorization: Bearer <your_access_token> -
响应:
json 复制代码 { "logged_in_as": "admin" }
-
安全注意事项
-
设置过期时间:
-
默认情况下,JWT 是永久有效的。建议设置令牌过期时间,例如:
python 复制代码 from datetime import timedelta app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(hours=1)
-
-
使用 HTTPS:
- 在生产环境中,务必使用 HTTPS 以防止令牌被中间人攻击窃取。
-
防止重复使用令牌:
- 实现令牌的黑名单机制,注销时将令牌加入黑名单。
总结
JWT 是一种轻量级的身份验证方式,因其安全性和跨平台特性而广泛应用于现代 Web 开发。在本篇文章中,我们了解了 JWT 的组成、应用场景,并通过 Flask 展示了如何使用 JWT 实现用户认证。掌握 JWT 的使用,不仅可以提升项目的安全性,还能提高系统的扩展能力。希望这篇文章对您有所帮助!