简体   繁体   中英

How to access(ask) token for user login

I have used Django Rest Framework for Rest API and django-oauth-toolkit for token based authentication. I have designed and api for user registration. When user is registered, a token is generated and saved to the database. I want user login from that token. I mean a token based authentication because i want to develop a mobile application. I can get access_token using curl when sending request for logging in but how do i implement in view so that app sends a post request to 127.0.0.1:8000/o/token asking for the token so that the request contains username, password, client_id and client_secret. The server then receives the credentials and if they are valid it returns the access_token. The rest of the time it should query the server using that token.

views.py

class UserLoginAPI(APIView):
    permission_classes = [AllowAny]
    serializer_class = UserLoginSerializer

    def post(self, request, *args, **kwargs):
        access_token = AccessToken.objects.get(token=request.POST.get('access_token'), expires__gt=timezone.now()) # error is shown here. I get None
        data = request.data
        serializer = UserLoginSerializer(data=data)
        if serializer.is_valid(raise_exception=True):
            new_data = serializer.data
            return Response(new_data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializers.py

class UserCreateSerializer(ModelSerializer):
    class Meta:
        model = User
        extra_kwargs = {"password": {"write_only": True}}

    def create(self, validated_data):
        username = validated_data['username']
        first_name = validated_data['first_name']
        last_name = validated_data['last_name']
        email = validated_data['email']
        password = validated_data['password']
        confirm_password = validated_data['password']
        user_obj = User(
                username = username,
                first_name = first_name,
                last_name = last_name,
                email = email
            )
        user_obj.set_password(password)
        user_obj.save()
        if user_obj:
            expire_seconds = oauth2_settings.user_settings['ACCESS_TOKEN_EXPIRE_SECONDS']
            scopes = oauth2_settings.user_settings['SCOPES']

            application = Application.objects.get(name="Foodie")
            expires = datetime.now() + timedelta(seconds=expire_seconds)
            access_token = AccessToken.objects.create(user=user_obj, 
                                                    application=application,
                                                    token = generate_token(),
                                                    expires=expires, 
                                                    scope=scopes)
        return validated_data


class UserLoginSerializer(ModelSerializer):
    # token = CharField(allow_blank=True, read_only=True)
    username = CharField()
    class Meta:
        model = User
        fields = [
            'username',
            'password',
            # 'token',

        ]
        extra_kwargs = {"password":
                            {"write_only": True}
                            }

So if you want a api to get token depend on username and password will look like this:

def get_token(request):
    username = request.POST.get("username")
    password = request.POST.get("password")
    .... # other parameters
    try:
        user = User.objects.get(username=username, password=password)
    except ObjectDoesNotExist:
        return HttpResponse("Can't find this user")
    else:
        try:
            access_token = AccessToken.objects.get(user=user)
        except ObjectDoesNotExist:
            return HttpResponse("Haven't set any token")
        else:
            return HttpResponse(access_token)

If you want to use DRF to handle this:

@api_view(['POST'])
def get_token(request):
    # get token by query just like above
    serializer = TokenSerializer(data=access_token.token) #you can pass more parameters to data if you want, but you also have to edit your TokenSerializer
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Your TokenSerializer:

class TokenSerializer(ModelSerializer):
    class Meta:
        model = AccessToken
        field = (token,)

EDIT

It depends

  • Web, you post your username and password to login api, your browser store session in your cookies.
  • Mobile, you post your username and password to login api, server response the token then you store it in your mobile, maybe keychain when you are developing IOS app.And send it as http header when you want to access the server, how-can-i-get-all-the-request-headers-in-django

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM