与 Django Rest Framework 的非用户连接的自定义身份验证

     2023-02-24     193

关键词:

【中文标题】与 Django Rest Framework 的非用户连接的自定义身份验证【英文标题】:Custom Authentication for non-user connection with Django Rest Framework 【发布时间】:2015-09-10 00:06:41 【问题描述】:

我已使用 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'

哈希将在设备端计算为 sha256(salt + udid + current_time) 将在 /login 内部的 DRF 端计算相同的哈希值,以比较并生成将保存在 REDIS 中并返回响应的令牌。

所有未来的请求都会将此令牌作为标头传递,这将在自定义 Permission 类中进行检查。

我的问题:

    我想为请求类设置一个自定义属性,例如 request.device, request.device.is_authenticated()

我应该把这个功能放在哪里?

    您发现我的方法有问题吗?也许是改进的建议?

【问题讨论】:

这是 this question 的副本,但我目前没有标记。 【参考方案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,并且可以将这个身份验证类子类化以更直接地使用它;为简单起见,我只是让设备在他们的请求中包含 X-UDID 标头。

还请注意,与令牌身份验证机制一样,您必须将此方法与 HTTPS 一起使用,否则 UDID 将以纯文本形式发送,从而允许某人冒充设备。

【讨论】:

【参考方案2】:

您可以继承 DRF 的 BaseAuthentication 类并覆盖 .authenticate(self, request) 方法。 成功验证后,此函数应返回(设备,无)。这将在 request.user 属性中设置设备对象。 您可以在您的设备模型类中实现 is_authenticated()。

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

将 APICustomAuthentication 添加到“DEFAULT_AUTHENTICATION_CLASSES” 在设置中。

更多详情可here

【讨论】:

这不是一个好主意,因为如果您返回 device,那么 request.user 在您的上下文中将是 device

无法让 CORS 与内容类型一起使用 - Django Rest Framework

】无法让CORS与内容类型一起使用-DjangoRestFramework【英文标题】:CannotgetCORStoworkwithcontenType-DjangoRestFramework【发布时间】:2013-04-2701:15:00【问题描述】:我在这个愚蠢的小问题上浪费了一整天!我在前端使用django-rest-framework作为我... 查看详情

Django Rest Framework:非模型服务

】DjangoRestFramework:非模型服务【英文标题】:DjangoRestFramework:Non-modelservice【发布时间】:2014-06-1009:52:43【问题描述】:我一直在使用django-rest-framework来创建与模型一起使用的服务。现在我需要创建一个服务来接收一些数据,对... 查看详情

将 StreamingHttpResponse 与 Django Rest Framework CSV 一起使用

】将StreamingHttpResponse与DjangoRestFrameworkCSV一起使用【英文标题】:UsingStreamingHttpResponsewithDjangoRestFrameworkCSV【发布时间】:2018-03-2312:33:08【问题描述】:我有一个标准的DRFWeb应用程序,它为其中一条路线输出CSV数据。渲染整个CSV表... 查看详情

将 Django Rest Framework 与序列化程序一起使用时出现 AttributeError

】将DjangoRestFramework与序列化程序一起使用时出现AttributeError【英文标题】:AttributeErrorwhileusingDjangoRestFrameworkwithserializers【发布时间】:2015-04-2921:17:03【问题描述】:我正在关注位于here的使用DjangoRestFramework的教程,但我不断收到... 查看详情

视图集中视图的 Django Rest Framework 自定义模式

】视图集中视图的DjangoRestFramework自定义模式【英文标题】:DjangoRestFrameworkcustomschemaforviewinviewset【发布时间】:2018-10-1818:51:39【问题描述】:我有一个使用Django和DjangoRESTFramework构建的API。我有一个模型,它返回一些与典型Django... 查看详情

为啥 Django REST Framework 提供不同的身份验证机制

】为啥DjangoRESTFramework提供不同的身份验证机制【英文标题】:WhydoesDjangoRESTFrameworkprovidedifferentAuthenticationmechanisms为什么DjangoRESTFramework提供不同的身份验证机制【发布时间】:2014-08-2108:47:38【问题描述】:为什么DjangoRESTFramework实... 查看详情

django-rest-framework 数据表列分表

】django-rest-framework数据表列分表【英文标题】:django-rest-frameworkdatatablescolumnsbreaktable【发布时间】:2021-02-2019:00:03【问题描述】:第1部分我让我的数据表与obj迭代一起工作,但我正在移动到DRF-datatables..虽然我让示例站点运行没... 查看详情

如何覆盖与响应 django rest framework 序列化程序一起返回的返回序列化程序对象

】如何覆盖与响应djangorestframework序列化程序一起返回的返回序列化程序对象【英文标题】:howtooverridereturnedserializerobjectthatisreturnedwiththeresponsedjangorestframeworkserializer【发布时间】:2019-11-2013:33:28【问题描述】:我有一个djangorest... 查看详情

05.django搜索与过滤(代码片段)

...son/django-filterhttps://django-filter.readthedocs.io/en/master/guide/rest_framework.htmlhttps://django-filter.readthedocs.io/en/master/ref/filters.htmlhttps://github.com/carltongibson/django-filterpipinstalldjango-filterINSTALLED_APPS=[...‘django_filters‘,]‘DEFAULT_FILTER_BACKENDS‘:(‘djan... 查看详情

Django 序列化器与 rest_framework 序列化器

】Django序列化器与rest_framework序列化器【英文标题】:Djangoserializersvsrest_frameworkserializers【发布时间】:2020-07-0913:44:06【问题描述】:Djangoserializers与rest_frameworkserializers有什么区别?我制作了一个webapp,我希望API成为项目创建的... 查看详情

记录对 django-rest-framework 的请求

】记录对django-rest-framework的请求【英文标题】:Loggingrequeststodjango-rest-framework【发布时间】:2013-03-1219:37:12【问题描述】:出于调试目的,我想使用Django的日志记录机制来记录每个“到达”django-rest-framework门口的传入请求。Djagno... 查看详情

处理 django rest framework + vue SPA auth

】处理djangorestframework+vueSPAauth【英文标题】:Handlingdjangorestframework+vueSPAauth【发布时间】:2019-02-2013:46:39【问题描述】:对于单页应用程序(当然是使用Vue路由器),我如何才能获得与django为经过身份验证的用户(用于检索用户... 查看详情

Django Rest Framework 中是不是曾经使用过 Django 表单?

】DjangoRestFramework中是不是曾经使用过Django表单?【英文标题】:AreDjangoformseverusedinDjangoRestFramework?DjangoRestFramework中是否曾经使用过Django表单?【发布时间】:2019-10-2815:48:48【问题描述】:DRF教程包含以下关于DRF序列化程序与Djang... 查看详情

基于 Django Rest Framework 中权限的不同查询集

】基于DjangoRestFramework中权限的不同查询集【英文标题】:differentquerysetbasedonpermissionsinDjangoRestFramework【发布时间】:2021-03-1706:53:42【问题描述】:我已经看到了这个link,但我没有找到任何与我的问题相关的信息来帮助解决它。... 查看详情

Django Rest Framework 中嵌套 URL 的相关资源

】DjangoRestFramework中嵌套URL的相关资源【英文标题】:RelatedresourcesonanestedURLinDjangoRestFramework【发布时间】:2019-12-2314:12:30【问题描述】:我有两个模型,Foo和Bar。Bar有一个指向Foo的外键。我有一个用于Foo的ModelViewSet,我希望路由/... 查看详情

django-rest-framework-datatables 和 Django Parler 的翻译字段

】django-rest-framework-datatables和DjangoParler的翻译字段【英文标题】:django-rest-framework-datatablesandDjangoParler\'stranslationfield【发布时间】:2019-08-1006:01:16【问题描述】:我有带有翻译字段的模型。classDevice(TranslatableModel):translations=Translat 查看详情

如何使用 Django REST Framework 实现实时更新?

】如何使用DjangoRESTFramework实现实时更新?【英文标题】:Howtoimplementreal-timeupdateswithDjangoRESTFramework?【发布时间】:2014-07-1019:49:29【问题描述】:我有一个需要与服务器紧密同步的客户端应用程序。到目前为止,我一直在使用民... 查看详情

django-rest-framework 按日期过滤=无

】django-rest-framework按日期过滤=无【英文标题】:django-rest-frameworkfilterbydate=None【发布时间】:2014-02-2611:35:00【问题描述】:我正在使用django-rest-framework和django-filter。我需要检索date属性为None的小部件列表,但无论我尝试什么查询... 查看详情