Django Rest 框架 JWT 和自定义身份验证后端

2024-04-09

我有一个自定义用户模型并创建了一个自定义身份验证后端。我在用Django 休息框架 http://www.django-rest-framework.org/, and Django 休息框架 JWT http://getblimp.github.io/django-rest-framework-jwt/#extending-jsonwebtokenauthentication用于令牌认证。

用户模型:

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(
        unique=True,
        max_length=254,
    )
    first_name = models.CharField(max_length=15)
    last_name = models.CharField(max_length=15)
    mobile = models.IntegerField(unique=True)
    date_joined = models.DateTimeField(default=timezone.now)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    objects = UserManager()
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name', 'mobile']

验证后端:

class EmailOrMobileAuthBackend(object):
    def authenticate(self, username=None, password=None):
        try:
            user = get_user_model().objects.get(email=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            if username.isdigit():
                try:
                    user = get_user_model().objects.get(mobile=username)
                    if user.check_password(password):
                        return user
                except User.DoesNotExist:
                    return None
            else:
                return None

    def get_user(self, user_id):
        try:
            return get_user_model().objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

并在settings.py中添加:

AUTHENTICATION_BACKENDS = ('accounts.email_mobile_auth_backend.EmailOrMobileAuthBackend',)

在登录 django 管理站点时,电子邮件和手机号码都可以很好地验证用户身份。但是,当我尝试使用用户获取令牌时Django 休息框架 JWT http://getblimp.github.io/django-rest-framework-jwt/#usage,我收到错误:

curl -X POST -d "[email protected] /cdn-cgi/l/email-protection&password=123123" http://localhost/api-token-auth/

"non_field_errors": [
    "Unable to log in with provided credentials."
  ]

我还在 Rest 框架的默认身份验证中添加了自定义身份验证后端类,但它仍然不起作用:

REST_FRAMEWORK = {
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'accounts.email_mobile_auth_backend.EmailOrMobileAuthBackend',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
}

我缺少什么?为什么它在登录 django 管理站点时工作,但在使用 django Rest Framework jwt 获取令牌时出现错误?

update

我按照建议制作了另一个身份验证后端并将其添加到DEFAULT_AUTHENTICATION_CLASSES,但即使这样也不起作用。

class DrfAuthBackend(BaseAuthentication):
    def authenticate(self, username=None, password=None):
        try:
            user = get_user_model().objects.get(email=username)
            if user.check_password(password):
                return user, None
        except User.DoesNotExist:
            if username.isdigit():
                try:
                    user = get_user_model().objects.get(mobile=username)
                    if user.check_password(password):
                        return user, None
                except User.DoesNotExist:
                    return None
            else:
                return None

设置:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAdminUser',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'accounts.email_mobile_auth_backend.EmailOrMobileAuthBackend',
        'accounts.email_mobile_auth_backend.DrfAuthBackend',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
}

update

改变args在 auth 类中username to email似乎有助于获得auth_token但同样无法登录管理站点。

class EmailOrMobileAuthBackend(object):
    def authenticate(self, email=None, password=None):
        try:
            user = get_user_model().objects.get(email=email)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            if email.isdigit():
                try:
                    user = get_user_model().objects.get(mobile=email)
                    if user.check_password(password):
                        return user
                except User.DoesNotExist:
                    return None
            else:
                return None

    def get_user(self, user_id):
        try:
            return get_user_model().objects.get(pk=user_id)
        except User.DoesNotExist:
            return None 

您应该检查DRF文档 http://www.django-rest-framework.org/api-guide/authentication/#custom-authentication用于自定义身份验证后端。

我认为您的自定义身份验证后端正在破坏它,您可以通过从 DRF 设置中删除您的来解决它:

REST_FRAMEWORK = {
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
}

或者通过修复你的,这基本上与 Django 自定义身份验证不同,因为你应该从authentication.BaseAuthentication它返回一个元组。

from rest_framework import authentication


class DrfAuthBackend(authentication.BaseAuthentication):
    def authenticate(self, email=None, password=None):
        try:
            user = get_user_model().objects.get(email=email)
            if user.check_password(password):
                return user, None
        except User.DoesNotExist:
            if email.isdigit():
                try:
                    user = get_user_model().objects.get(mobile=email)
                    if user.check_password(password):
                        return user, None
                except User.DoesNotExist:
                    return None
            else:
                return None

然后在 DRF 设置中使用它:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAdminUser',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'accounts.email_mobile_auth_backend.DrfAuthBackend',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
}

对于 Django 登录:

class EmailOrMobileAuthBackend(object):
    def authenticate(self, username=None, password=None):
        try:
            user = get_user_model().objects.get(email=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            if username.isdigit():
                try:
                    user = get_user_model().objects.get(mobile=username)
                    if user.check_password(password):
                        return user
                except User.DoesNotExist:
                    return None
            else:
                return None

    def get_user(self, user_id):
        try:
            return get_user_model().objects.get(pk=user_id)
        except User.DoesNotExist:
            return None 

然后进行设置:

AUTHENTICATION_BACKENDS = ('accounts.email_mobile_auth_backend.EmailOrMobileAuthBackend',)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django Rest 框架 JWT 和自定义身份验证后端 的相关文章

随机推荐

  • 具有自由 CORS 政策的公开托管图像? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在做一些将图像加载到画布上的测试 并且正在使用私下里在我们的 aws cdn 上托管图像 这个 c
  • 如何找到 ROI 并检测内部标记?

    我是计算机视觉的初学者 我有一个关于检测和跟踪的问题 我想检测下图中的白色矩形 以确定感兴趣的区域并检测红色标记的轮廓 但我不想利用颜色信息来检测标记 谁能给我关于如何做到这一点的建议 如果您只想检测圆圈 则可以使用经过调整的霍夫变换 ht
  • 具有有序索引的 R 向量-向量匹配

    这里我有两个字符串向量 它们的顺序很重要并且无法更改 vec1 lt c carrot carrot carrot apple apple mango mango cherry cherry vec2 lt c cherry apple 我
  • 可通过属性名称或索引选项访问的结构

    我对 Python 非常陌生 并试图弄清楚如何创建一个具有可通过属性名称或索引访问的值的对象 例如 os stat 返回 stat result 或 pwd getpwnam 返回 struct passwd 的方式 在试图弄清楚这一点时
  • alloca可以完全替代吗?

    我读过很多地方alloca已过时 不应使用 而应使用可变长度数组 我的问题是这样的 是alloca完全可以用变长数组代替 在我的特定实例中 我有一些看起来像这样的东西 typedef struct int value size t size
  • 如何在 Kotlin 中编写以下代码来实现回调

    我如何像java一样用Kotlin编写 Callback callback new Callback Override public void getCallback ServerResponse serverResponse var ca
  • 基于 RCP 的应用程序的 P2 更新失败

    我尝试通过 P2 更新站点更新基于 Eclipse RCP 3 5 的应用程序 该应用程序包含两个功能 产品是由Eclipse Buckminster P2 更新站点的创建是产品构建的一部分 当通过菜单开始更新时 Update gt Che
  • 为什么这个未使用的 self.hash 方法会导致“无法将字符串转换为整数”错误?

    我正在跑过Lynda Rails 3 教程 http www lynda com Ruby on Rails 3 tutorials essential training 55960 2 html 在某一时刻 在名为 access cont
  • 如何检测重复数据?

    我有一个简单的联系人数据库 但用户输入重复数据时遇到问题 我已经实现了一个简单的数据比较 但不幸的是 输入的重复数据并不完全相同 例如 姓名拼写错误 或者一个人输入 Bill Smith 另一个人输入 William Smith 表示同一个
  • 使用 $(function 等启动 javascript 代码

    我正在研究 Backbone 和来自的待办事项示例应用程序http todomvc com http todomvc com 我注意到有 3 种方法可以在文件中启动代码 function code here function code he
  • Swift 3 LPCM 录音机 |错误:kAudioFileInvalidPacketOffsetError

    下面的录音机仅在第一次时有效 如果您尝试第二次录音 则在尝试 AudioFileWritePackets 时会出现错误 kAudioFileInvalidPacketOffsetError 知道为什么会发生这种情况吗 先感谢您 存储库位于此
  • Spring & JPA:按需创建数据库模式和表

    JPA Spring 是否有可能在运行时创建 删除具有自定义名称和相应表 由 Entity 注释给出 的数据库模式 例如当用户按下按钮时 我只知道关于javax persistence schema generation属性 它们在我的应用
  • 带圆角和锯齿状弧形边框的正方形

    我想知道是否可以用纯 CSS 制作一个带有圆角和缩进边框的正方形 目前我有这个 custom square position relative display block width 75px height 75px border 2px
  • goimports 需要忽略供应商包

    我正在尝试实施dep在我的项目中 这一切都运行良好 但它还添加了一个供应商目录 我现在需要更新我的工具以忽略此目录 否则我提供的软件包将被修改 或者我会收到警告误报 我目前正在使用以下工具 goimports w go vet go lin
  • 将 DataGridView 导出到 Excel 的简单方法

    我正在尝试将 DataGridView 数据复制到 Excel 并且使用以下代码 public static void ExportToExcel DataGridView dgView Microsoft Office Interop E
  • 如何防止对象被垃圾收集?

    如何防止对象被垃圾收集 是否有任何通过最终确定或幻像引用或任何其他方法的方法 我在一次采访中被问到这个问题 面试官建议finalize 可以使用 保留一个参考 如果您的对象过早被收集 则表明您的应用程序设计中存在错误 垃圾收集器仅收集应用程
  • HTML5 Canvas 沿着带有坐标的路径拖动图像

    是否可以拥有一个坐标数组并仅沿着这些坐标拖放图像 我想只使用 javascript 而不使用 javascript 库 我一直在摸不着头脑 一直在谷歌上搜索这个问题 但找不到如何做到这一点或者是否可能 Demo http jsfiddle
  • “此列列表没有匹配的唯一键或主键”。但主键确实存在

    所以我正在练习一些 sql 编码来进行测试 但我无法获得外键来引用主键 这是不起作用的表 CREATE TABLE ASSIGNMENT ASSIGN ID NUMBER 2 NOT NULL START DATE DATE END DAT
  • MYSQL:使用 union 将两个表合并为一个表

    我必须用另外两个表制作一个表 并使用联合 有效的查询是 SELECT FROM tabel1 UNION SELECT FROM tabel2 现在我要做的就是将此结果 数据 放入表3 我已经拥有的表 其列与表1和表2中的列相同 谁能帮我
  • Django Rest 框架 JWT 和自定义身份验证后端

    我有一个自定义用户模型并创建了一个自定义身份验证后端 我在用Django 休息框架 http www django rest framework org and Django 休息框架 JWT http getblimp github io