如何使用Django REST Framework在JWT Token中存储JWT Token

时间:2017-11-21 07:30:14

标签: django python-3.x django-rest-framework django-rest-framework-jwt

我们将JWT Token与Django REST Framework一起使用。 商店JWT Token和我想在我的数据库中存储JWT Token。因为我将此API用于移动应用。

这里创建JWT令牌

class LoginView(APIView):
     permission_classes = [permissions.AllowAny]

    def post(self, request, format=None):
        """
        Return a Valid token if username and password
        is valid for a given client
        """
        try:
            username = request.data['username']
            password = request.data['password']
            user = authenticate(username=user.username, password=password)
            if user is not None:
                if user.is_active:
                    login(request, user)
                    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
                    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

                    payload = jwt_payload_handler(user)
                    token = jwt_encode_handler(payload)

                    ind = Individual.objects.filter(user_id=user.id).first()
                    ind.login_flag = True
                    ind.save()

这里,我使用了JWT令牌验证

class LogoutView(APIView):
    permission_classes = (IsAuthenticated, )
    authentication_classes = (JSONWebTokenAuthentication, )

    def post(self, request, format=None):
        .......
        .......

它适用于邮递员的JWT Token验证。但我想在哪里存储令牌以及如何在我的数据库中存储JWT令牌。

3 个答案:

答案 0 :(得分:1)

正如@Vijesh在评论中提到的,存储JWT令牌不是正确的方法。从DRF文档中,

  

与内置的TokenAuthentication方案不同,JWT身份验证   不需要使用数据库来验证令牌。

由于您使用django-rest-framework-jwt包进行JWT令牌身份验证。您还可以使用其apis来检索或刷新令牌。

在用户名和&无法提供密码用于检索或刷新应在Authorization标头中使用带有JWT令牌的受保护URL。因此,登录后,使用收到的令牌构造Authorization标头。 (注意不要错过标题中的JWT部分)

Authorization: JWT <your_token>

卷曲样本

curl -H "Authorization: JWT <your_token>" http://localhost:8000/protected-url/

答案 1 :(得分:1)

使用JWT的一个主要方面是您不想在数据库中存储令牌。存储jwt将破坏无状态身份验证的目的。

您只需验证令牌,加密就会处理其余部分。用于创建的秘密,JWT会对其进行验证,以防止任何阻碍。此外,您需要在ssl上实现jwt实现,以避免令牌劫持。

您通常不会在JWT中存储任何安全数据,但您可以通过加密有效负载来实现。正如JWE规范中所述。

答案 2 :(得分:0)

正如该线程上的其他人所建议的那样,重点不是将JWT存储在数据库中。它用于无状态验证。您应该能够使用机密生成和检索令牌。

在Django中完成此操作的一种方法是使用SECRET_KEY对JWT中的数据进行编码和解码,例如:

import jwt

from django.conf import settings
from django.contrib.auth import get_user_model
from your_project import custom_exceptions as exc


def get_token_for_user(user, scope):
    """
    Generate a new signed token containing
    a specified user limited for a scope (identified as a string).
    """
    data = {
        "user_%s_id" % (scope): str(user.id),
    }
    return jwt.encode(data, settings.SECRET_KEY).decode()


def get_user_for_token(token, scope):
    """
    Given a selfcontained token and a scope try to parse and
    unsign it.

    If max_age is specified it checks token expiration.

    If token passes a validation, returns
    a user instance corresponding with user_id stored
    in the incoming token.
    """
    try:
        data = jwt.decode(token, settings.SECRET_KEY)
    except jwt.DecodeError:
        raise exc.NotAuthenticated("Invalid token")

    model_cls = get_user_model()

    try:
        user = model_cls.objects.get(pk=data["user_%s_id" % (scope)])
    except (model_cls.DoesNotExist, KeyError):
        raise exc.NotAuthenticated("Invalid token")
    else:
        return user

函数get_token_for_user将令牌的user_idscope绑定在一起,并使用密钥对其进行编码。只有知道SECRET_KEY的人才能解码它。

get_token_for_userget_user_for_token是实用工具,一旦您从HTTP_AUTHORIZATION标头获得令牌,就可以使用它来验证令牌是否已成功解码和有效。

这些实用程序功能还为您创建的每个令牌都支持scope。因此,例如,您可以说此特定令牌仅用于authentication,并将作用域称为authentication

这些实用程序功能接受的scope参数只是一个字符串,因此您可以使用可以想到的任何范围,并且在对特定API调用进行解码时,您会知道令牌应该在什么范围内可用内。

您可以根据需要修改它们,以支持JWT进行身份验证。