如何对DRF django强制授权?

时间:2017-03-22 18:31:31

标签: python django django-models django-rest-framework django-authentication

我是Django世界的新手。

我已经为我的REST API实现了TokenAuthentication

  

settings.py

'DEFAULT_AUTHENTICATION_CLASSES': (
    'auth.authentication.TokenAuthentication',
),
  

authentication.py

class TokenAuthentication(RestTokenAuthentication):

    model = RestAPIToken

    def authenticate_credentials(self, key):
        try:
            token = self.model.objects.get(key=key)
        except self.model.DoesNotExist:
            if self.model.objects.has_expired(key):
                raise SessionExpired()
            raise exceptions.AuthenticationFailed(_('Invalid token.'))
        # Django auth framework expects
        # (user, auth) tuple. However, here we don't need user object.
        # So, keeping it None
        return None, token
  

views.py

class HistoryViewSet(viewsets.ModelViewSet):
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

    queryset = History.objects.all()
    serializer_class = HistorySerializer
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('contract_id',)
  

models.py

class RestAPIToken(models.Model):

    # This model does not inherits from DRF Token to avoid including
    # rest.authtoken app in INSTALLED_APPS and user may have multiple tokens
    # so ForeignKey field should be used (one active token and many expired for example)

    key     = models.CharField(max_length=40, primary_key=True, default=generate_token)
    user_id = models.IntegerField()
    created = models.DateTimeField(auto_now_add=True)
    expire  = models.DateTimeField(default=get_expiration_date)
    objects = TokenManager()

    def __str__(self):
        return self.key

    def invalidate(self):
        self.expire = timezone.now()
        self.save()

    def refresh(self):
        self.expire = get_expiration_date()
        self.save()

    def is_valid(self):
        return self.expire > timezone.now()

    class Meta:
        db_table = "rest_restapitoken"

现在,如果我提供Authorization标题,它的效果非常好。但是,如果我根本不提供Auth标头,它仍然可以正常工作。我没有用户模型。我不需要User模型,因为我不想检查它是否有效。因此,完全跳过User模型。

我不明白,没有Authorization标题,为什么请求成功执行?

1 个答案:

答案 0 :(得分:0)

对我来说这很有效:

settings.py

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

<强> API / views.py

@api_view(['GET', 'POST'])
def app_info(request):
    ...
    return Response({"status": "success"})

<强>终端

$ http http://localhost:8000/api/app_info/

HTTP/1.0 401 UNAUTHORIZED
Allow: POST, OPTIONS, GET
Content-Type: application/json
Date: Wed, 22 Mar 2017 19:51:37 GMT
Server: WSGIServer/0.1 Python/2.7.10
Set-Cookie: sessionid=l7he7vjjs37r4m6gwxdnl5pnqfnxanc8; expires=Thu, 23-Mar-2017 19:51:37 GMT; httponly; Max-Age=86400; Path=/
WWW-Authenticate: Token
X-Frame-Options: SAMEORIGIN

{
    "detail": "Authentication credentials were not provided."
}


$ http GET http://localhost:8000/api/app_info/ 'Authorization: Token 36900c7f8dedf8b3404e2aaefb22cf2adc42680d'

HTTP/1.0 201 CREATED
Allow: POST, OPTIONS, GET
Content-Type: application/json
Date: Wed, 22 Mar 2017 20:25:00 GMT
Server: WSGIServer/0.1 Python/2.7.10
Set-Cookie: sessionid=wrc2erou68gsbsjkpcjxdggqmhtnsfmh; expires=Thu, 23-Mar-2017 20:25:00 GMT; httponly; Max-Age=86400; Path=/
X-Frame-Options: SAMEORIGIN

{
    "status": "success",
}