设置 HttpOnly Cookie 存储 JWT示例

发布于:2025-09-08 ⋅ 阅读:(13) ⋅ 点赞:(0)

Flask 示例:设置 HttpOnly Cookie 存储 JWT

from flask import Flask, make_response, request, jsonify
import jwt
import datetime

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'

@app.route('/login', methods=['POST'])
def login():
    # 模拟登录成功后的用户信息
    user_id = 123
    token = jwt.encode(
        {'user_id': user_id, 'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1)},
        app.config['SECRET_KEY'],
        algorithm='HS256'
    )

    # 创建响应对象
    resp = make_response(jsonify({'message': '登录成功'}))

    # 设置 HttpOnly Cookie
    resp.set_cookie(
        'access_token',         # Cookie 名称
        token,                  # Cookie 值(JWT)
        httponly=True,          # 禁止 JS 访问,防 XSS
        secure=False,           # 生产环境应设为 True(仅 HTTPS)
        samesite='Lax',         # 防 CSRF,推荐 Lax 或 Strict
        max_age=3600            # 有效期 1 小时
    )

    return resp

@app.route('/protected')
def protected():
    token = request.cookies.get('access_token')
    if not token:
        return jsonify({'error': '未授权'}), 401

    try:
        payload = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
        return jsonify({'user_id': payload['user_id']})
    except jwt.ExpiredSignatureError:
        return jsonify({'error': 'Token 已过期'}), 401

解析亮点

  • set_cookie() 设置了 HttpOnly 属性,防止 JS 访问。

  • secure=False 仅用于开发环境,生产环境必须启用 HTTPS。

  • samesite='Lax' 防止跨站请求伪造(CSRF)。

  • request.cookies.get() 用于读取 Cookie 中的 Token。

Django 示例:设置 HttpOnly Cookie 存储 JWT

from rest_framework.views import APIView
from rest_framework.response import Response
from django.conf import settings
from django.utils import timezone
import jwt

class LoginView(APIView):
    def post(self, request):
        user_id = 123  # 模拟登录成功
        payload = {
            'user_id': user_id,
            'exp': timezone.now() + timezone.timedelta(hours=1)
        }
        token = jwt.encode(payload, settings.SECRET_KEY, algorithm='HS256')

        response = Response({'message': '登录成功'})

        # 设置 HttpOnly Cookie
        response.set_cookie(
            key='access_token',
            value=token,
            httponly=True,
            secure=not settings.DEBUG,
            samesite='Lax',
            max_age=3600
        )

        return response

class ProtectedView(APIView):
    def get(self, request):
        token = request.COOKIES.get('access_token')
        if not token:
            return Response({'error': '未授权'}, status=401)

        try:
            payload = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
            return Response({'user_id': payload['user_id']})
        except jwt.ExpiredSignatureError:
            return Response({'error': 'Token 已过期'}, status=401)

解析亮点

  • response.set_cookie() 设置 HttpOnly Cookie。

  • secure=not settings.DEBUG:开发环境允许 HTTP,生产强制 HTTPS。

  • request.COOKIES.get() 读取 Cookie 中的 Token。

  • 使用 jwt.decode() 验证 Token 合法性和过期时间。

安全建议(适用于 Flask 和 Django)

项目 建议配置
httponly ✅ 必须开启,防止 XSS
secure ✅ 生产环境必须开启 HTTPS
samesite ✅ 推荐 'Lax''Strict'
max_age 根据业务设置有效期
Token刷新 建议使用 Refresh Token + 自动刷新机制


网站公告

今日签到

点亮在社区的每一天
去签到