3

我们将 JWT 令牌与 Django REST 框架一起使用。在哪里存储 JWT 令牌,我想在我的数据库中存储 JWT 令牌。因为我将此 API 用于移动应用程序。

这里创建 JWT Token

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 令牌验证一起正常工作。但我想在哪里存储令牌以及如何在我的数据库中存储 JWT 令牌。

4

3 回答 3

3

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

在 Django 中实现此目的的一种方法是使用SECRET_KEYJWT 中的数据编码和解码,例如:

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

该函数将令牌的andget_token_for_user绑定在一起,并使用密钥对其进行编码。一个人可能只有在已知的情况下才能对其进行解码。user_idscopeSECRET_KEY

get_token_for_user&get_user_for_token是从标头中获取 Token 后可以使用的实用程序函数,HTTP_AUTHORIZATION以验证令牌是否已成功解码且有效。

这些实用程序功能还支持scope您创建的每个令牌。因此,例如,您可以说这个特定的标记只是 forauthentication并将范围称为authentication.

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

您可以根据需要修改这些以支持 JWT 进行身份验证。

于 2018-06-23T07:06:22.650 回答
2

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

您只需验证令牌,其余的由密码学处理。用于创建的秘密,JWT 验证它是否受到任何阻碍。此外,您需要通过 ssl 实现 jwt 实现,以避免令牌劫持。

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

于 2018-04-06T15:53:24.090 回答
2

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

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

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

在无法为检索或刷新提供用户名和密码的情况下,应在 Authorization 标头中使用带 JWT 令牌的受保护 url。所以登录后,用收到的令牌构造 Authorization 头。(注意不要错过标头中的 JWT 部分)

Authorization: JWT <your_token>

卷曲样本

curl -H "Authorization: JWT <your_token>" http://localhost:8000/protected-url/
于 2017-11-22T05:23:18.153 回答