Django:使用中间件更新 JWT 并将其设置为 HttpOnly cookie Response() 返回 django.template.response.ContentNotRenderedError

问题描述

我有一个自定义中间件,我在使用 HTTP_AUTHORIZATION cookie 时将 SimpleJWR HttpOnly 添加到每个授权请求中。此外,我还添加代码来检查 access 令牌是否有效。如果没有,则使用 requests 发送请求,获取新的 access 令牌并将其设置为 HttpOnly cookie。到目前为止,我可以在过期后获取新的 access 令牌。但是,我发送请求的 url 返回此错误

raise ContentNotRenderedError(
django.template.response.ContentNotRenderedError: The response content must be rendered before it can be accessed.

在第一个请求时它起作用了。它返回响应并将令牌保存为 HttpOnly cookie,但在令牌过期后,如果我再次发出请求,而不是(我想要发生的事情)将令牌保存为 HttpOnly cookie 并返回再次相同的响应,它返回错误

我认为问题出在 response 语句中。我的中间件:

import jwt
import datetime
import requests
import json

from rest_framework.response import Response
from django.conf import settings

class AuthorizationHeaderMiddleware:
    def __init__(self,get_response=None):
        self.get_response = get_response

    def __call__(self,request):
        access_token = request.COOKIES.get('access')
        refesh_token = request.COOKIES.get('refresh')
        print(refesh_token)
        # check if the access token is valid
        # if not,send new access token to cookie
        if access_token:
            key = settings.SECRET_KEY
        try:
            decoded_access_token = jwt.decode(access_token,key,algorithms=["HS256"])
        except jwt.ExpiredSignatureError:
            # Signature has expired
            print("expired; sending for new token")
            url = 'http://127.0.0.1:8000/api/token/refresh/'
            data = {"refresh": refesh_token}
            resp = requests.post(
                url,data=json.dumps(data),headers = {'content-type': 'application/json'}
                )
            result = resp.json()
            new_access_token = result['access']
            response = Response()
            response.set_cookie('access',new_access_token,httponly=True)
            response.set_cookie('set','new')
            return response

            request.Meta['HTTP_AUTHORIZATION'] = f'Bearer {access_token}'
        return self.get_response(request)

这个错误是怎么来的,我该如何解决

解决方法

试试这个:

def __call__(self,request):
    access_token = request.COOKIES.get('access')
    refesh_token = request.COOKIES.get('refresh')
    print(refesh_token)
    # check if the access token is valid
    # if not,send new access token to cookie
    if access_token is not None:
        key = settings.SECRET_KEY
    else:
        return Response({"Error" : "No token found"})
    try:
        decoded_access_token = jwt.decode(access_token,key,algorithms=["HS256"])
        request.META['HTTP_AUTHORIZATION'] = f'Bearer {access_token}'
        return self.get_response(request)
    except jwt.ExpiredSignatureError:
        # Signature has expired
        print("expired; sending for new token")
        url = 'http://127.0.0.1:8000/api/token/refresh/'
        data = {"refresh": refesh_token}
        resp = requests.post(
            url,data=json.dumps(data),headers = {'content-type': 'application/json'}
            )
        result = resp.json()
        new_access_token = result['access']
        response = Response()
        response.set_cookie('access',new_access_token,httponly=True)
        response.set_cookie('set','new')
        request.META['HTTP_AUTHORIZATION'] = f'Bearer {new_access_token}'
        
        return self.get_response(request)