Fra*_*eli 5 jwt django-rest-framework
在以不安全的方式使用djangorestframework-jwt一年后,我终于决定我希望以一种更安全的方式使其工作。
我到处都读到了在本地客户端(例如,本地存储)中保存JWT令牌的方法不好,最好的解决方案是使用HttpOnly cookie。
我知道HttpOnly cookie确实是一个cookie,可以保存但不能被浏览器读取。所以我认为它可以像下面这样使用:
我现在正尝试通过使用HttpOnly cookie来使用djangorestframework-jwt,而JWT_AUTH_COOKIE配置似乎是最合适的配置:
如果除了授权标头之外还想使用http cookie作为令牌的有效传输方式,则可以设置JWT_AUTH_COOKIE字符串。您在此处设置的字符串将用作在请求令牌时将在响应标头中设置的cookie名称。令牌验证过程还将调查此cookie(如果已设置)。如果请求中同时包含标头和cookie,则“授权”标头具有优先权。
默认值为“无”,创建令牌时不设置cookie,或在验证令牌时不接受。
将字符串值赋予JWT_AUTH_COOKIE之后,我收到了预期的httpOnly cookie。
问题:
当我调用refreshToken时,得到以下响应:
{"token":["This field is required."]}
Run Code Online (Sandbox Code Playgroud)
是的,我没有在请求的HEADER中发送任何令牌,这就是我想要的,因为客户端不应该将其保存在任何地方。
这就是我感到困惑的地方:
如果我从现在开始对客户端对服务器的每个请求都没错,则应将cookie添加到请求中。
看到标题中没有传递令牌后,服务器是否应该检查Cookie?如果不是这样,应该如何工作?
您观察到的问题是正确的,因为cookie尚未实现刷新令牌api。
这可能是代码本身的错误。但是没有什么可以限制您解决此问题。
您也可以修补视图,以照顾基于cookie的身份验证。将下面的代码添加到您的顶部,urls.py
它将完成相同的工作
from rest_framework_jwt.settings import api_settings
if api_settings.JWT_AUTH_COOKIE:
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework_jwt.serializers import RefreshJSONWebTokenSerializer
from rest_framework_jwt.views import RefreshJSONWebToken
RefreshJSONWebTokenSerializer._declared_fields.pop('token')
class RefreshJSONWebTokenSerializerCookieBased(RefreshJSONWebTokenSerializer):
def validate(self, attrs):
if 'token' not in attrs:
if api_settings.JWT_AUTH_COOKIE:
attrs['token'] = JSONWebTokenAuthentication().get_jwt_value(self.context['request'])
return super(RefreshJSONWebTokenSerializerCookieBased, self).validate(attrs)
RefreshJSONWebToken.serializer_class = RefreshJSONWebTokenSerializerCookieBased
Run Code Online (Sandbox Code Playgroud)
我已将此中间件添加到我的 Django (3.1) 中:
class YankTokenRefreshFromHeaderIntoTheBody(MiddlewareMixin):
"""
for Django Rest Framework JWT's POST "/token-refresh" endpoint --- check for a 'token' in the request.COOKIES
and if, add it to the body payload.
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, *view_args, **view_kwargs):
if request.path == '/v1/token-refresh' and 'token' in request.COOKIES:
data = json.loads(request.body)
data['token'] = request.COOKIES['token']
request._body = json.dumps(data).encode('utf-8')
return None
Run Code Online (Sandbox Code Playgroud)
然后我在我的这里添加了它settings
:
MIDDLEWARE = [
'myproj.utils.middleware.YankTokenRefreshFromHeaderIntoTheBody',
...
...
]
Run Code Online (Sandbox Code Playgroud)
就是这样。Django REST 框架 JWT 的令牌刷新端点现在可以工作,因为它会在那里找到“令牌”键/值。
需要注意的几点:
'token'
作为持有 tte JWT 令牌的 cookie 的名称。你的当然可能会有所不同。/v1/token-refresh
-- 如果您使用原始命名端点,您也需要更改它。 归档时间: |
|
查看次数: |
478 次 |
最近记录: |