继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

JWT 用户校验学习:从入门到实践

四季花海
关注TA
已关注
手记 293
粉丝 42
获赞 161

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 的生成涉及以下步骤:使用算法生成 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 的有效性。这包括:

  1. 检查 JWT 的签名是否正确
  2. 检查 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
  • 安全性最佳实践
  1. 严格限制 JWT 的密钥,不要使用默认密钥。
  2. 使用 HTTPS 保护 JWT,防止中间人攻击。
  3. 将 JWT 存储在安全的位置,如 HTTP-only Cookie,防止 XSS 攻击。
  4. 不要在 JWT 中包含敏感信息,如密码或信用卡号。
  5. 使用 JWT 时,确保服务器端和客户端都进行严格的验证和安全性检查,以防止非法操作。
打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP