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

     2023-03-10     134

关键词:

【中文标题】Django rest 框架 JWT 和自定义身份验证后端【英文标题】:Django rest framework JWT and custom authentication backend 【发布时间】:2017-10-27 19:53:51 【问题描述】:

我有一个自定义用户模型并创建了一个自定义身份验证后端。我正在使用django rest framework 和django rest framework JWT 进行令牌认证。

用户模型:

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 rest framework JWT 为用户获取令牌时,出现错误:

curl -X POST -d "email=admin@gmail.com&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获取令牌时出错?

更新

我按照建议创建了另一个身份验证后端并将其添加到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',
    ),

更新

将身份验证类中的argsusername 更改为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 

【问题讨论】:

您最终解决了这个问题吗?在使用django-rest-frameworkdjango-rest-framework-jwt 时遇到了类似的问题,我需要允许用户通过用户名或电子邮件或mobile_number 登录来获取JWT 令牌 @lukik 我正在使用两个身份验证后端。一个用于 django 管理员,另一个用于其余 api。 这两个后端是否允许用户通过电子邮件或手机登录?如果是的话,你介意分享一下你是怎么做的,尤其是对于其余的 API 吗?谢谢。 @lukik 是的,当然。我创建了两个身份验证后端(两者基本相同)。你可以找到他们here 和there。然后在设置中我沿线添加了these。 【参考方案1】:

您应该检查 DRF documentation 以获取自定义身份验证后端。

我认为您的自定义身份验证后端破坏了它,您可以通过从 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',)

【讨论】:

我已经尝试了您的建议并更新了问题,但仍然无法正常工作。但是,将authentication() 方法中的参数从username 更改为email 无需将其添加到DEFAULT_AUTHENTICATION_CLASSES 即可完成工作。但同样无法登录到管理站点。 The Django custom authentication 不支持电子邮件作为关键字参数,您应该只将它用于 Django 并为 DRF 写一个不同的【参考方案2】:

在您的 settings.py 文件中,添加以下内容:

AUTH_USER_MODEL = 'accounts.email_mobile_auth_backend.EmailOrMobileAuthBackend'

【讨论】:

使用 Django REST 框架进行 JWT 身份验证

】使用DjangoREST框架进行JWT身份验证【英文标题】:JWTAuthenticationwithDjangoRESTFramework【发布时间】:2019-05-0222:51:38【问题描述】:我在验证对DjangoREST端点的请求时遇到了一些问题。我有一个指向rest_framework_jwt.views.obtain_jwt_token的toke... 查看详情

使用 otp 获取 api 令牌的 Django REST 框架的 JWT 身份验证

】使用otp获取api令牌的DjangoREST框架的JWT身份验证【英文标题】:JWTAuthenticationwithDjangoRESTFrameworkusingotpforgettingapitokens【发布时间】:2021-07-0610:11:57【问题描述】:我有一个自定义用户登录,我使用移动OTP验证,并且在我的项目中... 查看详情

使用 Django Rest 框架进行 JWT 令牌身份验证

】使用DjangoRest框架进行JWT令牌身份验证【英文标题】:JWTTokenAuthenticationwithDjangoRestFramework【发布时间】:2018-12-1513:12:03【问题描述】:我在我的Django-Rest应用程序上使用reactnative前端进行令牌身份验证时遇到了一些问题。我一直... 查看详情

如何在 django rest 框架中验证 jwt 身份验证中的令牌

】如何在djangorest框架中验证jwt身份验证中的令牌【英文标题】:howtovalidatetokeninjwtauthenticationindjangorestframework【发布时间】:2021-10-2712:33:59【问题描述】:如何在SimpleJWT身份验证中验证JWT令牌。如果令牌访问令牌已过期,我需要... 查看详情

如何在 django-rest 框架中验证我的 JWT 令牌?

】如何在django-rest框架中验证我的JWT令牌?【英文标题】:HowtoauthenticatemyJWTtokenindjango-restframework?【发布时间】:2019-10-3123:59:32【问题描述】:我在Djangorest框架中实现了JWT令牌身份验证,它获取了我的令牌,但我遇到的问题是我... 查看详情

Django Rest Framework JWT 未提供身份验证凭据

】DjangoRestFrameworkJWT未提供身份验证凭据【英文标题】:AuthenticationcredentialswerenotprovidedwithDjangoRestFrameworkJWT【发布时间】:2019-02-1919:38:50【问题描述】:我在带有Typscript前端的DjangoREST框架中使用JWT实现令牌身份验证时遇到问题。... 查看详情

Django Rest 框架 JWT

】DjangoRest框架JWT【英文标题】:DjangoRestFrameworkJWT【发布时间】:2015-10-1922:37:00【问题描述】:我正在使用DjangoRestFramework为我的应用程序构建API,并希望实现DjangoRestFramework-JWT以进行令牌身份验证。这些步骤看起来很简单,但是... 查看详情

Django Rest Framework 中的 JWT 身份验证错误“无效签名”

】DjangoRestFramework中的JWT身份验证错误“无效签名”【英文标题】:JWTAuthenticationError"InvalidSignature"inDjangoRestFramework【发布时间】:2018-03-2806:15:29【问题描述】:我是Python和DjangoREST框架的新手,我正在尝试使用JWT(https://jpadi... 查看详情

Django 通道 JWT 身份验证

】Django通道JWT身份验证【英文标题】:DjangoChannelsJWTAuthentication【发布时间】:2021-03-2513:44:23【问题描述】:我正在尝试访问Consumer.py范围内的用户,并从数据库中获取一些与用户相关的模型。但是,我用于验证所有websocket连接的... 查看详情

带有 jwt 身份验证的 django rest api 要求 csrf 令牌

】带有jwt身份验证的djangorestapi要求csrf令牌【英文标题】:djangorestapiwithjwtauthenticationisaskingforcsrftoken【发布时间】:2018-06-2216:08:10【问题描述】:我是djangorestapi框架的新手。我正在为其余api使用基于JWT令牌的身份验证,并具有以... 查看详情

如何使用 Django rest 框架来延长 JWT 会话令牌?

】如何使用Djangorest框架来延长JWT会话令牌?【英文标题】:HowdoIusetheDjangorestframeworktoprolongaJWTsessiontoken?【发布时间】:2021-11-2920:30:15【问题描述】:我将Django3.2与django.auth.contrib应用程序和djangorestframework-jwt==1.11.0一起使用。在收... 查看详情

django rest framework jwt 使用电子邮件和密码进行身份验证

】djangorestframeworkjwt使用电子邮件和密码进行身份验证【英文标题】:djangorestframeworkjwtauthenticationwithemailandpassword【发布时间】:2017-01-1823:21:34【问题描述】:我有一个django项目,我将djangorest框架用于我的RESTAPI,并使用JWT进行身... 查看详情

Django REST 框架、JWT 和 request.session

】DjangoREST框架、JWT和request.session【英文标题】:Djangorestframework,JWTandrequest.session【发布时间】:2015-08-1307:56:38【问题描述】:我使用DjangoREST框架和JWT进行身份验证,一切正常,但是......我需要在登录时将有关用户的信息保存在... 查看详情

Django Rest JWT 身份验证 - 刷新令牌

】DjangoRestJWT身份验证-刷新令牌【英文标题】:DjangoRestJWTauthentication-refreshtoken【发布时间】:2019-02-2721:01:09【问题描述】:我的DjangoREST应用程序和JWT身份验证模块(https://jpadilla.github.io/django-rest-framework-jwt)在刷新令牌阶段出现问... 查看详情

Django + Auth0 JWT 身份验证拒绝解码

】Django+Auth0JWT身份验证拒绝解码【英文标题】:Django+Auth0JWTauthenticationrefusingtodecode【发布时间】:2016-03-2907:42:24【问题描述】:我正在尝试使用django-rest-framework在我的DjangoRESTAPI中实现基于Auth0JWT的身份验证。我知道有一个可用于... 查看详情

Django Rest Framework JWT 身份验证测试

】DjangoRestFrameworkJWT身份验证测试【英文标题】:DjangoRestFrameworkJWTAuthenticationTest【发布时间】:2015-06-0108:39:43【问题描述】:我正在设置DRF以使用JWT令牌身份验证。我似乎处于DRF-JWT说它工作正常,但我无法成功运行登录测试的地... 查看详情

Django rest框架认证测试

】Djangorest框架认证测试【英文标题】:DjangorestframeworkAuthentcationTesting【发布时间】:2015-03-2912:45:54【问题描述】:我正在尝试使用JWT进行身份验证的测试用例,在这种情况下使用django-rest-framework-jwt,然后使用curl我得到下一个,... 查看详情

如何从 django rest 框架访问 jwt 令牌到 Angular 前端

】如何从djangorest框架访问jwt令牌到Angular前端【英文标题】:Howtoaccessajwttokenfromadjangorestframeworktoangularfrontend【发布时间】:2021-08-0610:13:11【问题描述】:我创建了一个使用jwt进行身份验证的DRFapi,令牌存储在一个cookie中。我可以... 查看详情