如何使用DRF djangorestframework-simplejwt包将JWT令牌存储在HttpOnly cookie中? [英] How to store JWT tokens in HttpOnly cookies with DRF djangorestframework-simplejwt package?

本文介绍了如何使用DRF djangorestframework-simplejwt包将JWT令牌存储在HttpOnly cookie中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一段时间以来,我一直在使用 djangorestframework-simplejwt ,现在我想将JWT存储在cookie中(而不是localstorage或前端状态),以便客户端发出的每个请求,包含令牌.

I've been using djangorestframework-simplejwt for a while and now I want to store the JWT in the cookies (instead of localstorage or front-end states) so that every request that the client makes, contains the token.

对此进行了一些研究,我发现最相关的结果是此stackoverflow问题,作者使用的是 djangorestframework-jwt 软件包,该软件包具有名为 JWT_AUTH_COOKIE 的cookie的预配置设置.因此,想着要切换到该软件包,但最终发现该软件包是几乎死了.

So did some research on it and the most relevant result I found was this stackoverflow question, in which the author is using djangorestframework-jwt package which has a pre-configured setting for cookies called JWT_AUTH_COOKIE. So figured switching to that package but then ended up finding out that the package is pretty much dead.

尽管对于 djangorestframework有一个叉子建议使用-jwt 代替,我想知道是否仍然可以使用 djagnorestframework_simplejwt 本身在HttpOnly cookie中设置JWT?

Although there is a fork for the djangorestframework-jwt that is recommended to use instead, I was wondering is there anyway to set the JWTs in HttpOnly cookies with the djagnorestframework_simplejwt itself?

推荐答案

遵循httpcode cookie标志和CSRF保护.

With httponly cookie flag and CSRF protection follow this code.

双方在移动应用和网络应用中都很有用.

Both side very useful in mobile app and webapp..

urls.py:

...
path('login/',LoginView.as_view(),name = "login"),
...

view.py:

from rest_framework_simplejwt.tokens import RefreshToken
from django.middleware import csrf

def get_tokens_for_user(user):
    refresh = RefreshToken.for_user(user)
        
    return {
        'refresh': str(refresh),
        'access': str(refresh.access_token),
    }

class LoginView(APIView):
    def post(self, request, format=None):
        data = request.data
        response = Response()        
        username = data.get('username', None)
        password = data.get('password', None)
        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                data = get_tokens_for_user(user)
                response.set_cookie(
                                    key = settings.SIMPLE_JWT['AUTH_COOKIE'], 
                                    value = data["access"],
                                    expires = settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME'],
                                    secure = settings.SIMPLE_JWT['AUTH_COOKIE_SECURE'],
                                    httponly = settings.SIMPLE_JWT['AUTH_COOKIE_HTTP_ONLY'],
                                    samesite = settings.SIMPLE_JWT['AUTH_COOKIE_SAMESITE']
                                        )
                csrf.get_token(request)
                email_template = render_to_string('login_success.html',{"username":user.username})    
                login = EmailMultiAlternatives(
                    "Successfully Login", 
                    "Successfully Login",
                    settings.EMAIL_HOST_USER, 
                    [user.email],
                )
                login.attach_alternative(email_template, 'text/html')
                login.send()
                response.data = {"Success" : "Login successfully","data":data}
                
                return response
            else:
                return Response({"No active" : "This account is not active!!"},status=status.HTTP_404_NOT_FOUND)
        else:
            return Response({"Invalid" : "Invalid username or password!!"},status=status.HTTP_404_NOT_FOUND)

authenticate.py:

from rest_framework_simplejwt.authentication import JWTAuthentication
from django.conf import settings

from rest_framework.authentication import CSRFCheck
from rest_framework import exceptions

def enforce_csrf(request):
    """
    Enforce CSRF validation.
    """
    check = CSRFCheck()
    # populates request.META['CSRF_COOKIE'], which is used in process_view()
    check.process_request(request)
    reason = check.process_view(request, None, (), {})
    if reason:
        # CSRF failed, bail with explicit error message
        raise exceptions.PermissionDenied('CSRF Failed: %s' % reason)

class CustomAuthentication(JWTAuthentication):
    
    def authenticate(self, request):
        header = self.get_header(request)
        
        if header is None:
            raw_token = request.COOKIES.get(settings.SIMPLE_JWT['AUTH_COOKIE']) or None
        else:
            raw_token = self.get_raw_token(header)
        if raw_token is None:
            return None

        validated_token = self.get_validated_token(raw_token)
        enforce_csrf(request)
        return self.get_user(validated_token), validated_token

settings.py:

....
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'authentication.authenticate.CustomAuthentication',
    ),
}

SIMPLE_JWT = {
.....
'AUTH_COOKIE': 'access_token',  # Cookie name. Enables cookies if value is set.
'AUTH_COOKIE_DOMAIN': None,     # A string like "example.com", or None for standard domain cookie.
'AUTH_COOKIE_SECURE': False,    # Whether the auth cookies should be secure (https:// only).
'AUTH_COOKIE_HTTP_ONLY' : True, # Http only cookie flag.It's not fetch by javascript.
'AUTH_COOKIE_PATH': '/',        # The path of the auth cookie.
'AUTH_COOKIE_SAMESITE': 'Lax',  # Whether to set the flag restricting cookie leaks on cross-site requests.
                                # This can be 'Lax', 'Strict', or None to disable the flag.
}

---------或------------

通过使用middleware.py:

--------- OR ------------

By using middleware.py:

如何使用中间件进行身份验证

必须:

withCredentials均为True.

withCredentials is True for both side..

如有疑问,请发表评论.

Any doubt please comment..

这篇关于如何使用DRF djangorestframework-simplejwt包将JWT令牌存储在HttpOnly cookie中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆