JWT 用户校验学习从 JWT 的基本概念和结构开始,介绍了 JWT 的生成方法及用户校验流程。文章详细讲解了 JWT 的头部、载荷和签名的构成,并通过代码示例展示了如何生成和验证 JWT。
JWT 简介JWT(JSON Web Token)是一种开放标准(RFC 7519),用于通过使用 JSON 对象在各方之间安全地传输信息。JWT 可以确保信息的安全传输,通常用于身份验证和信息交换。JWT 的主要优点包括跨域性、紧凑性和无状态性。JWT 工作原理如下:客户端在请求中发送 JWT,服务器通过验证 JWT 的签名来确认请求者的身份和权限。JWT 包含三部分:头部、载荷和签名。
JWT 的基本结构JWT 由三部分组成:头部、载荷和签名,每部分由点(.)分隔,形成一个字符串。JWT 的结构如下:
<Header>.<Payload>.<Signature>
- 头部(Header)
头部包含了声明(通常为两个键值):加密的算法以及令牌的类型。例如,一个简化的头部:
{
"alg": "HS256",
"typ": "JWT"
}
- 载荷(Payload)
载荷是 JWT 的主体部分,包含声明(声明是关于实体的声明,如用户的身份、权限等)。载荷中的声明可以被分为三类:
- 公共声明:被定义为不敏感的声明,可以在彼此之间进行共享和使用。
- 私有声明:不是公共声明,可以在应用中根据情况自定义。
- 标准声明:不是公共声明,但在 JWT 这个标准中被预留了。
例如,一个载荷:
{
"userId": "123456",
"username": "user01",
"exp": 1684272000
}
- 签名(Signature)
签名是对头部和载荷的组合进行加密生成的。例如,使用 HMAC SHA256 算法生成签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
其中,secret
是一个密钥,用于保证 JWT 的安全性。
JWT 的生成涉及以下步骤:使用算法生成 JWT、配置密钥和有效期、并生成签名。在本示例中,我们将使用 HMAC SHA256 算法。首先,将头部和载荷分别进行 base64 编码:
import base64
# JSON 对象转换成 base64 编码的字符串
def encode_base64(json_obj):
return base64.urlsafe_b64encode(json.dumps(json_obj).encode('utf-8')).decode('utf-8')
header = {
"alg": "HS256",
"typ": "JWT"
}
payload = {
"userId": "123456",
"username": "user01",
"exp": 1684272000
}
encoded_header = encode_base64(header)
encoded_payload = encode_base64(payload)
接下来,将编码后的 header 和 payload 连接并用 HMAC SHA256 算法和密钥进行签名:
import hashlib
import hmac
def generate_signature(encoded_header, encoded_payload, secret):
message = f"{encoded_header}.{encoded_payload}".encode('utf-8')
signature = hmac.new(secret.encode('utf-8'), message, hashlib.sha256).digest()
return base64.urlsafe_b64encode(signature).decode('utf-8')
secret = "secret_key"
signature = generate_signature(encoded_header, encoded_payload, secret)
最后,将三部分连接在一起生成 JWT:
jwt_token = f"{encoded_header}.{encoded_payload}.{signature}"
用户校验的基本流程
用户校验的基本流程包括接收 JWT、验证 JWT 的有效性以及解析 JWT 的载荷信息。
- 接收 JWT
客户端在请求中通过 HTTP 头字段(通常是 Authorization
)发送 JWT:
Authorization: Bearer <token>
- 验证 JWT 的有效性
服务器接收到请求后,首先需要验证 JWT 的有效性。这包括:
- 检查 JWT 的签名是否正确
- 检查 JWT 的载荷是否在有效期内
验证 JWT 的有效性可以通过以下步骤实现:
import json
import time
import base64
def decode_base64(data):
missing_padding = 4 - len(data) % 4
if missing_padding:
data += '=' * missing_padding
return base64.urlsafe_b64decode(data)
def parse_jwt(token, secret):
parts = token.split('.')
if len(parts) != 3:
raise ValueError('Invalid JWT format')
header = json.loads(decode_base64(parts[0]).decode('utf-8'))
payload = json.loads(decode_base64(parts[1]).decode('utf-8'))
signature = decode_base64(parts[2])
message = f"{parts[0]}.{parts[1]}".encode('utf-8')
valid_signature = hmac.new(secret.encode('utf-8'), message, hashlib.sha256).digest()
if signature != valid_signature:
raise ValueError('Invalid JWT signature')
if payload['exp'] < time.time():
raise ValueError('JWT expired')
return payload
- 解析 JWT 的载荷信息
在验证 JWT 有效之后,可以解析 JWT 的载荷信息并从中获取用户信息:
def authenticate(user_token):
secret = "secret_key"
try:
payload = parse_jwt(user_token, secret)
return payload
except Exception as e:
return None
实践案例:使用 JWT 进行用户校验
用户登录并获取 JWT:
def login(username, password):
# 假设这里进行用户名和密码的验证,并返回用户信息
user_info = {"userId": "123456", "username": "user01"}
exp = int(time.time()) + 3600 # 有效时间为 1 小时
payload = {"userId": user_info['userId'], "username": user_info['username'], "exp": exp}
jwt_token = generate_jwt(payload, "secret_key")
return jwt_token
通过 JWT 进行后续请求校验:
def protected_resource(user_token):
user_info = authenticate(user_token)
if not user_info:
return {"error": "Invalid JWT"}
return {"message": "Access granted", "userId": user_info['userId']}
构建简单的认证接口:
from flask import Flask, request
app = Flask(__name__)
@app.route('/login', methods=['POST'])
def login_api():
username = request.form.get('username')
password = request.form.get('password')
jwt_token = login(username, password)
return {"token": jwt_token}
@app.route('/protected_resource', methods=['GET'])
def protected_resource_api():
user_token = request.headers.get('Authorization', '').split('Bearer ')[1]
response = protected_resource(user_token)
return response
if __name__ == '__main__':
app.run()
常见问题及解决方案
- JWT 过期处理
当 JWT 过期时,客户端需要重新获取新的 JWT。这通常通过刷新令牌(refresh token)来实现。一个简单的 JWT 刷新过程示例如下:
def refresh_token(refresh_token):
# 验证刷新令牌,返回新的 JWT
new_jwt_token = generate_jwt(new_payload, "secret_key")
return new_jwt_token
- JWT 丢失或损坏的处理
当 JWT 丢失或损坏时,客户端需要重新登录以获取新的 JWT。例如,当 JWT 丢失时,用户可以调用 login
方法重新登录:
def handle_jwt_loss_or_damage():
# 重新登录获取新的 JWT
jwt_token = login(username, password)
return jwt_token
- 安全性最佳实践
- 严格限制 JWT 的密钥,不要使用默认密钥。
- 使用 HTTPS 保护 JWT,防止中间人攻击。
- 将 JWT 存储在安全的位置,如 HTTP-only Cookie,防止 XSS 攻击。
- 不要在 JWT 中包含敏感信息,如密码或信用卡号。
- 使用 JWT 时,确保服务器端和客户端都进行严格的验证和安全性检查,以防止非法操作。
共同学习,写下你的评论
评论加载中...
作者其他优质文章