Python案例怎么生成登录令牌?

wen python案例 16

本文目录导读:

Python案例怎么生成登录令牌?

  1. 使用JWT (JSON Web Token) - 最推荐
  2. 使用 itsdangerous - Flask常用
  3. 使用 hashlib + 随机数 - 简单实现
  4. Flask-JWT-Extended示例(完整Web应用)
  5. 安全建议
  6. 选择建议

我来介绍几种在Python中生成登录令牌的常见方法:

使用JWT (JSON Web Token) - 最推荐

安装依赖

pip install pyjwt

生成JWT令牌

import jwt
import datetime
from typing import Dict, Optional
# 密钥配置
SECRET_KEY = "your-secret-key-here"
ALGORITHM = "HS256"
def create_access_token(
    data: Dict,
    expires_delta: Optional[datetime.timedelta] = None
) -> str:
    """生成访问令牌"""
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.datetime.utcnow() + expires_delta
    else:
        # 默认24小时过期
        expire = datetime.datetime.utcnow() + datetime.timedelta(hours=24)
    to_encode.update({"exp": expire})
    token = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return token
def verify_token(token: str) -> Dict:
    """验证令牌"""
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        return payload
    except jwt.ExpiredSignatureError:
        raise Exception("Token已过期")
    except jwt.InvalidTokenError:
        raise Exception("无效的Token")
# 使用示例
def login(username: str, password: str) -> str:
    """登录函数"""
    # 这里应该是验证用户名和密码的逻辑
    if username == "admin" and password == "123456":
        token_data = {
            "sub": username,  # 用户标识
            "user_id": 1,
            "role": "admin"
        }
        token = create_access_token(
            data=token_data,
            expires_delta=datetime.timedelta(hours=2)
        )
        return token
    else:
        raise Exception("用户名或密码错误")
# 测试
if __name__ == "__main__":
    # 登录
    try:
        token = login("admin", "123456")
        print(f"生成的Token: {token}")
        # 验证Token
        payload = verify_token(token)
        print(f"Token解析结果: {payload}")
    except Exception as e:
        print(f"错误: {e}")

使用 itsdangerous - Flask常用

安装

pip install itsdangerous

示例代码

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from itsdangerous import BadSignature, SignatureExpired
class TokenManager:
    def __init__(self, secret_key: str, expires_in: int = 3600):
        """
        :param secret_key: 密钥
        :param expires_in: 过期时间(秒)
        """
        self.secret_key = secret_key
        self.expires_in = expires_in
        self.serializer = Serializer(
            secret_key=secret_key,
            expires_in=expires_in
        )
    def generate_token(self, user_data: dict) -> str:
        """生成令牌"""
        return self.serializer.dumps(user_data).decode('utf-8')
    def verify_token(self, token: str) -> dict:
        """验证令牌"""
        try:
            data = self.serializer.loads(token)
            return data
        except SignatureExpired:
            raise Exception("Token已过期")
        except BadSignature:
            raise Exception("无效的Token")
# 使用示例
token_manager = TokenManager(
    secret_key="my-secret-key",
    expires_in=7200  # 2小时
)
# 生成Token
user_info = {"user_id": 123, "username": "john"}
token = token_manager.generate_token(user_info)
print(f"生成的Token: {token}")
# 验证Token
try:
    data = token_manager.verify_token(token)
    print(f"验证成功: {data}")
except Exception as e:
    print(f"验证失败: {e}")

使用 hashlib + 随机数 - 简单实现

import hashlib
import random
import string
import time
import json
import base64
class SimpleToken:
    def __init__(self, secret_key: str):
        self.secret_key = secret_key
    def generate_token(self, user_id: int, username: str) -> str:
        """生成简单令牌"""
        # 创建payload
        payload = {
            "user_id": user_id,
            "username": username,
            "timestamp": int(time.time()),
            "random": ''.join(random.choices(string.ascii_letters + string.digits, k=8))
        }
        # 将payload转为JSON并编码
        payload_str = json.dumps(payload, sort_keys=True)
        payload_b64 = base64.b64encode(payload_str.encode()).decode()
        # 生成签名
        signature = hashlib.sha256(
            f"{payload_b64}{self.secret_key}".encode()
        ).hexdigest()
        # 组合Token
        token = f"{payload_b64}.{signature}"
        return token
    def verify_token(self, token: str) -> dict:
        """验证令牌"""
        try:
            payload_b64, signature = token.split('.')
            # 验证签名
            expected_signature = hashlib.sha256(
                f"{payload_b64}{self.secret_key}".encode()
            ).hexdigest()
            if signature != expected_signature:
                raise Exception("Token签名无效")
            # 解码payload
            payload_str = base64.b64decode(payload_b64).decode()
            payload = json.loads(payload_str)
            # 检查过期时间(这里设置24小时过期)
            current_time = int(time.time())
            if current_time - payload['timestamp'] > 86400:
                raise Exception("Token已过期")
            return payload
        except (ValueError, json.JSONDecodeError):
            raise Exception("无效的Token格式")
# 使用示例
token_mgr = SimpleToken("my-secret-key")
# 生成Token
token = token_mgr.generate_token(1, "john_doe")
print(f"生成的Token: {token}")
# 验证Token
try:
    data = token_mgr.verify_token(token)
    print(f"验证成功: {data}")
except Exception as e:
    print(f"验证失败: {e}")

Flask-JWT-Extended示例(完整Web应用)

from flask import Flask, request, jsonify
from flask_jwt_extended import (
    JWTManager, create_access_token, jwt_required, 
    get_jwt_identity, create_refresh_token
)
from datetime import timedelta
app = Flask(__name__)
# 配置
app.config['JWT_SECRET_KEY'] = 'super-secret-key'
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(hours=1)
app.config['JWT_REFRESH_TOKEN_EXPIRES'] = timedelta(days=30)
jwt = JWTManager(app)
# 模拟用户数据
users = {
    "admin": {"password": "123456", "role": "admin"},
    "user": {"password": "password", "role": "user"}
}
@app.route('/login', methods=['POST'])
def login():
    username = request.json.get('username')
    password = request.json.get('password')
    if not username or not password:
        return jsonify({"msg": "需要用户名和密码"}), 400
    user = users.get(username)
    if not user or user['password'] != password:
        return jsonify({"msg": "用户名或密码错误"}), 401
    # 创建访问令牌和刷新令牌
    access_token = create_access_token(
        identity=username,
        additional_claims={"role": user['role']}
    )
    refresh_token = create_refresh_token(identity=username)
    return jsonify({
        "access_token": access_token,
        "refresh_token": refresh_token
    }), 200
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
    current_user = get_jwt_identity()
    return jsonify({
        "message": f"欢迎 {current_user}!",
        "user": current_user
    }), 200
@app.route('/refresh', methods=['POST'])
@jwt_required(refresh=True)
def refresh():
    current_user = get_jwt_identity()
    new_token = create_access_token(identity=current_user)
    return jsonify({"access_token": new_token}), 200
if __name__ == '__main__':
    app.run(debug=True)

安全建议

  1. 使用HTTPS:始终在HTTPS下传输Token
  2. 设置合理的过期时间:避免Token长期有效
  3. 存储敏感信息:不要在Token中存储密码等敏感信息
  4. 密钥管理:保密JWT密钥,使用环境变量存储
  5. Token吊销:实现Token黑名单机制

选择建议

  • 生产环境:推荐使用JWT (pyjwt)
  • Flask应用:推荐Flask-JWT-Extended
  • 简单需求:可以使用itsdangerous
  • 学习目的:可以使用hashlib实现

这些方法各有优劣,根据你的具体需求选择合适的方案。

抱歉,评论功能暂时关闭!