django如何生成唯一的用户令牌

时间:2018-05-16 05:07:03

标签: django

我对令牌认证有点困惑。经过一些问题和尝试后,我设法创建了url网关以自动登录我的用户,但我只是通过使用user_id并将其传递出来而设法做到这一点。 url例如http://example.com/auth/login/?user_id=12但我更愿意使用?token=

我使用DRF示例了解如何制作自定义身份验证令牌并返回更多关于我的用户的数据,以便在我卷曲到url之后我回来了

{"token":"d5d86e55fd5ddd48298b2ac72c3ed96b7e30dd86","user_id":52}

现在我面临的问题是MyUser maching query does not exists这是正常的我在模型中没有令牌,所以我创建了一个

token = models.CharField(max_length=125, null=True, blank=True)

所以我可以克服DoesNotExist错误,但错误仍然存​​在。

我正在使用此hack进行网关登录

from django.contrib.auth import authenticate, login
from django.core.urlresolvers import reverse
from django.views.generic import View
from django.http import HttpResponseRedirect

from business_accounts.models.my_user import MyUser


class UrlGatewayLogin(View):

    def get(self, request, **kwargs):
        page_group = kwargs.get('page_group')
        token = request.GET.get('token')
        user = MyUser.objects.get(token=token)
        user.backend = 'django.contrib.auth.backends.ModelBackend'
        login(request, user)

        return HttpResponseRedirect(reverse('dashboard', args=(page_group, )))

每个用户的DRF令牌是唯一的,如何在django中生成令牌并将其用于我的网关?

1 个答案:

答案 0 :(得分:-1)

您需要安装Django-Rest-Framework并在设置中启用TokenAuthentication。

首先,您必须为您的用户模型编写序列化程序,然后使用序列化数据创建api视图以进行令牌身份验证。

例如(您也可以使用用户名而不是电子邮件): 在您的users / api / serializers.py文件中:

from django.utils.translation import ugettext_lazy as _

from rest_framework import serializers
from rest_framework.compat import authenticate

from ..models import User


class AuthTokenSerializer(serializers.Serializer):
    email = serializers.EmailField(label=_("Email Address"))
    password = serializers.CharField(
        label=_("Password"),
        style={'input_type': 'password'},
        trim_whitespace=False
    )

    def validate(self, data):
        email = data.get('email')
        password = data.get('password')

        if email and password:
            user = authenticate(email=email, password=password)

            if user:
                if not user.is_active:
                    msg = _('User account is deactivated.')
                    raise serializers.ValidationError(msg)
            else:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg)
        else:
            msg = _('Must include "email" and "password".')
            raise serializers.ValidationError(msg)

        data['user'] = user
        return data

然后在您的users / api / views.py文件中:

from rest_framework.response import Response

from .serializers import AuthTokenSerializer
from ..models import User


class ObtainAuthToken(APIView):
    throttle_classes = ()
    permission_classes = ()
    parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
    renderer_classes = (renderers.JSONRenderer,)
    serializer_class = AuthTokenSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data,
                                           context={'request': request})
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)
        return Response({'token': token.key, 'username':user.username})

然后在设置中,确保您已启用令牌身份验证:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    )
}

为了使用该令牌返回有关用户的数据,您需要在User模型上编写另一个序列化程序,包括要返回的字段,例如:

class UserDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = [
            'username', 'email', 'hobbies', 'language',
            'gender', 'birthday'
        ]

并编写另一个api视图,例如:

class UserDetailAPIView(RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = UserDetailSerializer

    def get_object(self):
        obj = get_object_or_404(User, username=self.request.user.username)
        return obj

关键是为您的模型编写序列化程序,以便可以在Internet上传输数据。