django DRF将auth_token设置为httponly cookie

2j4z5cfb  于 2023-11-20  发布在  Go
关注(0)|答案(1)|浏览(125)

我使用djoser库进行TokenAuthentication。但我不想将access_token发送到前端。因为它无法以安全的方式保存它。所以我将TokenView更改为这样:

from djoser.views import TokenCreateView
class TokenCreateView(TokenCreateView):

    def _action(self, serializer):
        token = utils.login_user(self.request, serializer.user)
        token_serializer_class = settings.SERIALIZERS.token
        
        response = Response() 
        data = token_serializer_class(token).data

        response.set_cookie(
            key = 'access_token', 
            value = data['auth_token'],
            secure = False,
            httponly = True,
            samesite = 'Lax'
        )

        response.data = {"Success" : "Login successfully","data":data}
        return response

字符串
我把access_token放到httponly cookies中。并创建了一个中间件:

def auth_token(get_response):
    def middleware(request):
        # when token is in headers in is not needed to add in from cookies
        logger.error(request.COOKIES.get('access_token'))

        if 'HTTP_AUTHORIZATION' not in request.META:

            token = request.COOKIES.get('access_token')
            if token:

                request.META['HTTP_AUTHORIZATION'] = f'Token {token}'

        return get_response(request)

    return middleware

MIDDLEWARE = [
    ...
    'apps.profiles.middlewares.auth_token',
    ...
]


这个中间件将access_token从cookie添加到header中。现在前端没有对auth_token的访问。并且更难窃取auth_token。这种方法合适吗?

lnxxn5zx

lnxxn5zx1#

感谢您的分享。出于同样的原因,我一直在寻找将访问令牌存储在本地存储中的替代方案-它不安全。我更改或添加了一些内容。
在create token视图中,我不会在响应中返回token--我的react前端不再需要管理它。我还确保了在本地开发之外,cookie是安全的。请注意,30天的max_age对于大多数网站来说可能不是一个好主意。

class TokenCreateView(djoser.views.TokenCreateView):
    def _action(self, serializer):
        token = utils.login_user(self.request, serializer.user)
        token_serializer_class = settings.SERIALIZERS.token

        response = Response()
        data = token_serializer_class(token).data

        response.set_cookie(
            key = "access_token",
            value = data["auth_token"],
            max_age = timedelta(days=30),
            secure = not is_localhost,
            httponly = True,
            samesite = "Strict"
        )

        response.data = "Welcome!"
        response.status_code = status.HTTP_200_OK
        return response

字符串
我认为你也应该在注销时删除cookie。

class TokenDestroyView(djoser.views.TokenDestroyView):
    """Use this endpoint to logout user (remove user authentication token)."""

    permission_classes = settings.PERMISSIONS.token_destroy

    def post(self, request):
        response = Response()
        response.delete_cookie("access_token")
        response.status_code = status.HTTP_204_NO_CONTENT
        utils.logout_user(request)
        return response


我还简化了中间件功能,因为我选择只支持cookie。

def auth_token(get_response):
    def middleware(request):
        token = request.COOKIES.get('access_token')
        if token:
            request.META['HTTP_AUTHORIZATION'] = f'Token {token}'

        return get_response(request)

    return middleware


为了完整性,我们确实需要更新URL。

# path("auth/", include("djoser.urls.authtoken")),
      path("auth/token/login/", core_views.TokenCreateView.as_view(), name="login"),
      path("auth/token/logout/", core_views.TokenDestroyView.as_view(), name="logout"),

相关问题