Rest API令牌基于身份验证。基本认证

时间:2017-06-24 10:10:09

标签: python django django-rest-framework

我已经使用rest_framework实现了基于令牌的身份验证,现在每件事都运行正常但我有一个问题,如果我使用basic-auth在标头中发送用户名和密码那么为什么我需要发送用户 - 带有效负载的名称和密码。当我在body部分发送包含用户名和密码的有效负载的请求时,请求的标题中没有用户名和密码,我得到以下作为回复:

{
  "detail": "CSRF Failed: CSRF token missing or incorrect."
}

当我在标题中发送用户名和密码而没有发送带有效负载的用户名和密码时,我得到以下回复:

{
  "detail": "Invalid username/password."
}

为什么我在发送有效负载时需要在标题部分发送用户名和密码。我对这个概念不太确定。任何人都可以解释并告诉我正确的方法。我使用了这个reference

以下是我的代码: authuser.py

"""Authentication classes for Django Rest Framework.
Classes:
    ExpiringTokenAuthentication: Authentication using extended authtoken model.
"""

from rest_framework import exceptions
from rest_framework.authentication import TokenAuthentication

from rest_framework_expiring_authtoken.models import ExpiringToken


class ExpiringTokenAuthentication(TokenAuthentication):

    """
    Extends default token auth to have time-based expiration.
    Based on http://stackoverflow.com/questions/14567586/
    """

    model = ExpiringToken

    def authenticate_credentials(self, key):
        """Attempt token authentication using the provided key."""
        if key == "2572e6dbe3b2e150764cd72712713b2975785197":
            token = self.model.objects.get(key=key)
        else:
            try:
                token = self.model.objects.get(key=key)
            except self.model.DoesNotExist:
                raise exceptions.AuthenticationFailed('Invalid token')

            if not token.user.is_active:
                raise exceptions.AuthenticationFailed('User inactive or deleted')

            #if token.expired():
             #   raise exceptions.AuthenticationFailed('Token has expired')

        return (token.user_id, token)

查看.py

 class ObtainExpiringAuthToken(ObtainAuthToken):

    """View enabling username/password exchange for expiring token."""
    model = ExpiringToken
    def post(self, request):
        try:
            payload=json.loads(request.body)
        except:
            return Response({'success':False,'message':'Invalid Payload.'})
        """Respond to POSTed username/password with token."""
        serializer = AuthTokenSerializer(data=request.data)
        if serializer.is_valid():
            token, _ = ExpiringToken.objects.get_or_create(
                user=serializer.validated_data['user']
            )
            if token.expired():
                # If the token is expired, generate a new one.
                token.delete()
                token = ExpiringToken.objects.create(
                    user=serializer.validated_data['user']
                )

            try:
                user = User.objects.get(id=token.user_id)
            except:
                return Response({'success':False,'message':'User does not exists.'})
    return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)

obtain_expiring_auth_token = ObtainExpiringAuthToken.as_view()

models.py:

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

class ExpiringToken(Token):

    """Extend Token to add an expired method."""

    class Meta(object):
        proxy = True

    def expired(self):
        """Return boolean indicating token expiration."""
        now = timezone.now()
        #if self.created < now - token_settings.EXPIRING_TOKEN_LIFESPAN:
         #   return True
        return True

settings.py:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
    )
}

1 个答案:

答案 0 :(得分:0)

获取此错误的唯一可能方法是启用SessionAuthentication。它默认全局启用。

http://www.django-rest-framework.org/api-guide/authentication/#setting-the-authentication-scheme

请仔细检查您的设置或在您的视图类中设置适当的设置以覆盖全局设置。