Django rest framework 使用HttpOnly Cookie的django rest框架

Django rest framework 使用HttpOnly Cookie的django rest框架,django-rest-framework,jwt,Django Rest Framework,Jwt,在以一种不安全的方式使用了一年多之后,我终于决定让它以一种更安全的方式工作 我到处都读到,在本地客户机(例如,本地存储)中保存JWT令牌是不好的,最好的解决方案是使用HttpOnly cookies 我知道HttpOnly cookie实际上是一种cookie,它可以被保存,但不能被浏览器读取。所以我认为它可以像下面这样使用: get_token:客户端通过发送用户和密码向服务器请求授权令牌:如果用户和密码有效,服务器将使用httpOnly cookie进行响应,该cookie可以存储,但客户

在以一种不安全的方式使用了一年多之后,我终于决定让它以一种更安全的方式工作

我到处都读到,在本地客户机(例如,本地存储)中保存JWT令牌是不好的,最好的解决方案是使用HttpOnly cookies

我知道HttpOnly cookie实际上是一种cookie,它可以被保存,但不能被浏览器读取。所以我认为它可以像下面这样使用:

  • get_token:客户端通过发送用户和密码向服务器请求授权令牌:如果用户和密码有效,服务器将使用httpOnly cookie进行响应,该cookie可以存储,但客户端无法读取
  • 从现在开始,客户端执行的每个请求都是授权的,因为在HttpOnly cookie中有一个有效的授权令牌
  • 刷新\u令牌:一旦客户端需要刷新令牌,它只需要请求一个刷新\u令牌:如果发送的cookie包含一个有效令牌,服务器将使用一个更新的HttpOnly cookie和新令牌进行响应
我现在正试图通过使用HttpOnly cookie来使用djangorestframework jwt,jwt_AUTH_cookie配置似乎是最合适的配置:

如果要将http COOKIE与授权标头一起用作令牌的有效传输,则可以将JWT_AUTH_COOKIE设置为字符串。您在此处设置的字符串将用作请求令牌时在响应头中设置的cookie名称。令牌验证过程还将检查此cookie(如果已设置)。如果请求中同时存在“Authorization”标头和cookie,则“Authorization”标头优先

默认值为“无”,创建令牌时未设置cookie,验证令牌时也未接受cookie

在给JWT_AUTH_COOKIE一个字符串值之后,我收到了一个预期的httpOnly COOKIE

问题是:

调用refreshToken时,我得到以下响应:

{"token":["This field is required."]}
是的,我没有在请求头中发送任何令牌,这正是我想要的,因为客户端不应该将其保存在任何地方

这就是我感到困惑的地方:

如果从现在起我对客户机向服务器发出的每个请求都没有错,那么应该将cookie添加到请求中

服务器在看到头中没有传递令牌后,不应该检查cookie吗?如果不是这样,它应该怎么工作


如果有人想为改进做出贡献,也在此处发布了一个Github问题:

您观察到的问题是正确的,因为刷新令牌api尚未与cookie一起实现

这可能是代码本身的一个bug。但没有任何东西限制您解决此问题

您也可以对视图进行修补,以处理基于cookie的身份验证。将下面的代码添加到
url.py的顶部,它将处理相同的问题

从rest\u framework\u jwt.settings导入api\u设置
如果api_settings.JWT_AUTH_COOKIE:
从rest\u framework\u jwt.authentication导入JSONWebTokenAuthentication
从rest\u framework\u jwt.serializers导入RefreshJSONWebTokenSerializer
从rest\u framework\u jwt.views导入RefreshJSONWebToken
RefreshJSONWebTokenSerializer.\u声明的\u字段.pop('token'))
类RefreshJsonWebTokenSerializerCookeBased(RefreshJSONWebTokenSerializer):
def验证(自身、属性):
如果“令牌”不在属性中:
如果api_settings.JWT_AUTH_COOKIE:
attrs['token']=JSONWebTokenAuthentication().get_jwt_值(self.context['request'])
返回super(RefreshJsonWebTokenSerializerCookie,self).validate(attrs)
RefreshJSONWebToken.serializer\u class=RefreshJSONWebTokenSerializerCookeBased

我已将此中间件添加到Django(3.1)中:

然后我将其添加到我的
设置中:

MIDDLEWARE = [
    'myproj.utils.middleware.YankTokenRefreshFromHeaderIntoTheBody',
    ...
    ...
]
就这样。Django REST framework JWT的令牌刷新端点现在可以工作了,因为它将在其中找到“令牌”键/值

需要注意的几件事:

  • 我选择了
    'token'
    作为持有tte JWT令牌的cookie的名称。当然,你的可能会有所不同
  • 我将端点的名称更改为
    /v1/token refresh
    ——如果您使用的是原始命名端点,您也需要更改该名称

  • 这听起来像是一个前沿问题。如果您使用的是axios,您将设置
    axios.defaults.withCredentials=true
    ,并且在收到cookie后,您必须设置头
    axios.defaults.headers.common['Authorization']='JWT'
    这方面有任何更新吗?@Francesco Meli-这对您有用吗<代码>djangrestframework jwt
    的行为与预期不符。我正在使用
    TokenAuthentication
    作为
    httponly
    cookie,但是我在处理被撤销的令牌客户端时遇到了问题,因为如果您将过期令牌与请求一起发送,Django将返回401。@zerohedge遗憾的是,我还没有时间测试它。不过我很快就要测试它了。请,如果你找到一个现实世界的工作解决方案,让我们都知道!我们有没有办法联系上?也许我们可以一起寻找解决方案。这件事我已经做了好几天都没用了。把回购协议的钥匙给这个人。。。。。。。。。。。。。。。。。。。。。。。。。
    MIDDLEWARE = [
        'myproj.utils.middleware.YankTokenRefreshFromHeaderIntoTheBody',
        ...
        ...
    ]