【问题标题】:Adding custom user authentication to django-rest-framework-simple-jwt将自定义用户身份验证添加到 django-rest-framework-simple-jwt
【发布时间】:2020-07-28 11:12:26
【问题描述】:

我想通过一次性密码以及 django 中常用的用户名/密码方法添加用户登录。为此,用户名/密码或用户名/OTP 从客户端发送到服务器,并且基于提供的字段对,如果用户通过身份验证,我需要返回访问和刷新令牌。我正在使用 django 的 simple-jwt。我知道我必须重写 TokenObtainPairView 和 TokenObtainSerializer。问题是,我想自己做字段验证部分。

在我的视图中,我覆盖了 simple-jwt 的默认视图。

#views.py

class MyTokenObtainPairView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer

我重写了如下的序列化器:

#serializers.py

class MyTokenObtainPairSerializer(TokenObtainPairSerializer):

    def validate(self, attrs):
        try:
            request = self.context["request"]
        except KeyError:
            pass

        try:
            request_data = json.loads(request.body)
            if("username" in request_data and "password" in request_data):
                # default scenario in simple-jwt  
                pass
            elif("username" in request_data and "otp" in request_data):                                   
                # validate username/otp manually and return access/token pair if successful
                pass

            else:
                # some fields were missing
                raise serializers.ValidationError({"username/otp or username/password" : "These fields are required"})

        except:
            pass

因此,如果客户端以以下一种可能的形式传递用户凭据,我将能够对其进行身份验证并返回令牌对。

{
   "username" : "Winston",
   "password" : "testpass"
}

{
    "username" : "Winston",
    "otp" : "testotp"
}

问题是,当我以第二种形式发送数据时,我得到400 BadRequest:password is required。如何自定义字段及其验证?

【问题讨论】:

  • 坚持使用单个序列化程序的原因是什么?为密码和 OTP 编写 2 个单独的序列化程序的另一种方法。

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


【解决方案1】:

正如 cmets 中提到的Saiful Azad,一种可能的方法是为每个场景使用单独的序列化程序。

#views.py

class MyTokenObtainPairView(TokenObtainPairView):
    def get_serializer_class(self):
        if ("otp" in self.request.data):
            return MyTokenObtainPairSerializer
        return TokenObtainPairSerializer

然后,您可以实现自己的序列化程序进行 otp 验证。我使用simple-jwt's implementation 来实现我自己的序列化程序并使用我的自定义身份验证方法。

【讨论】:

    【解决方案2】:

    在你的 urls.py

    # Imports
    from rest_framework_simplejwt.tokens import RefreshToken
    from django.contrib.auth.models import User
    from rest_framework.response import Response
    from rest_framework.decorators import api_view, permission_classes
    from rest_framework.permissions import AllowAny
    
    @api_view(['GET'])
    @permission_classes([AllowAny])
    def get_tokens_for_user(request):
    
        # find the user base in params
        user = User.objects.first()
    
        refresh = RefreshToken.for_user(user)
    
        return Response({ 
           'refresh': str(refresh),
           'access': str(refresh.access_token),
        })
    
    urlpatterns = [
        path('login', get_tokens_for_user, name="login")
    ]
    

    【讨论】:

      猜你喜欢
      • 2019-11-20
      • 2021-04-04
      • 2019-01-01
      • 2015-12-26
      • 1970-01-01
      • 2015-11-12
      • 2020-04-10
      • 2015-06-01
      • 2013-05-03
      相关资源
      最近更新 更多