簡體   English   中英

使用Django Rest Framework進行非用戶連接的自定義身份驗證

[英]Custom Authentication for non-user connection with Django Rest Framework

我已使用TokenAuthentication啟用了使用DRF的用戶身份驗證

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
         'rest_framework.authentication.TokenAuthentication',
         'rest_framework.authentication.SessionAuthentication'
    ),
    'DEFAULT_MODEL_SERIALIZER_CLASS':
        'rest_framework.serializers.ModelSerializer',
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.AllowAny',
    ),
    #'EXCEPTION_HANDLER': 'apps.core.exceptions.custom_exception_handler'

}

我有以下型號:

class Device(CreationModificationMixin):
    """
    Contains devices (WW controllers).  A device may be associated with the Owner
    """
    _STATUSES = (
        ('A', 'Active'), # when everything is okay
        ('I', 'Inactive'), # when we got nothing from SPA controllers for X minutes
        ('F', 'Failure'), # when controller says it has issues
    )

    _TYPES = (
        ('S', 'Spa'),
        ('P', 'Pool'),
    )

    udid    = models.CharField(max_length=255, verbose_name="Unique ID / MAC Address", help_text="MAC Address of WiFi controller", unique=True, null=False, blank=False, db_index=True)
    type    = models.CharField(max_length=1, choices=_TYPES, null=False, blank=False)
    title   = models.CharField(max_length=255, null=False, blank=False, db_index=True)
    status  = models.CharField(max_length=1, default='A', choices=_STATUSES)
    pinged  = models.DateTimeField(null=True)
    owner   = models.ForeignKey(Owner, verbose_name="Owner", null=True, blank=True, db_index=True)

    def __str__(self):
        return self.udid

這表示將向API端點發送離散請求的硬件設備,因此我需要對每個請求進行身份驗證,理想情況下使用基於令牌的標識,如

POST /api/devices/login 
{
   udid: '...mac address...',
   hash: '...sha256...hash string',
   time: '2015-01-01 12:24:30'
}

hash將在設備端計算為sha256(salt + udid + current_time),將在DRF端內計算相同的哈希值/ login以進行比較並生成將保存在REDIS中並返回響應的令牌。

所有將來的請求都將此標記作為標頭傳遞,將在自定義Permission類中進行檢查。

我的問題:

  1. 我想在請求類上設置一個自定義屬性,如request.device,request.device.is_authenticated()

我應該把這個功能放在哪里?

  1. 你覺得我的方法有問題嗎? 也許建議改進?

正如@ daniel-van-flymen指出的那樣,返回設備而不是用戶可能不是一個好主意。 所以我做的是創建一個擴展django.contrib.auth.models.AnonymousUserDeviceUser類,並在我的自定義身份驗證中返回(畢竟設備基本上是匿名用戶)。

from myapp.models import Device
from rest_framework import authentication 
from django.contrib.auth.models import AnonymousUser 
from rest_framework.exceptions import AuthenticationFailed 

class DeviceUser(AnonymousUser):

    def __init__(self, device):
        self.device = device 

    @property 
    def is_authenticated(self):
        return True 


class DeviceAuthentication(authentication.BaseAuthentication):

    def authenticate(self, request):
        udid = request.META.get("HTTP_X_UDID", None)
        if not udid:
            return None 

        try:
            device = Device.objects.get(udid=udid)
        except Device.DoesNotExist:
            raise AuthenticationFailed("Invalid UDID")

        if not device.active:
            raise AuthenticationFailed("Device is inactive or deleted")

        request.device = device 
        return (DeviceUser(device), None)

此代碼存在於myapp.authentication ,然后您可以將以下內容添加到您的設置中:

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "myapp.authentication.DeviceAuthentication", 
    )
}

您原始規范中的幾個注釋:我已在身份驗證器中修改了包含設備的請求,因此您可以執行request.device.is_authenticated ; 但是,用戶將是DeviceUser因此您也可以執行request.user.device.is_authenticated (只要您對device屬性進行適當的檢查)。

您的原始規范還要求實現TokenAuthentication ,並且可以將此身份驗證類子類TokenAuthentication更直接地使用它; 為簡單起見,我只是讓設備在其請求中包含X-UDID標頭。

另請注意,與令牌身份驗證機制一樣,您必須將此方法與HTTPS一起使用,否則UDID將以純文本格式發送,允許某人模擬設備。

您可以子類化DRF的BaseAuthentication類並覆蓋.authenticate(self,request)方法。 成功驗證后,此功能應返回(設備,無)。 這將在request.user屬性中設置設備對象。 您可以在Device模型類中實現is_authenticated()。

class APICustomAuthentication(BaseAuthentication):
    ---
    def  authenticate(self, request):
        ----
        return (device, None)    # on successful authentication

在設置中將APICustomAuthentication添加到“DEFAULT_AUTHENTICATION_CLASSES”。

更多細節可在此處獲得

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM