web-dev-qa-db-fra.com

Ajout d'une authentification utilisateur personnalisée à Django-rest-framework-simple-jwt

Je souhaite ajouter une connexion utilisateur via un mot de passe à usage unique ainsi que la méthode habituelle de nom d'utilisateur/mot de passe dans Django. Pour ce faire, le nom d'utilisateur/mot de passe ou le nom d'utilisateur/OTP sont envoyés du client au serveur et en fonction de la paire de champs fournie, je dois renvoyer le jeton d'accès et d'actualisation si l'utilisateur est authentifié. J'utilise simple-jwt de Django. Je sais que je dois remplacer TokenObtainPairView et TokenObtainSerializer. Le problème est que je veux faire moi-même la partie validation de champ.

Dans mes vues, je remplace la vue par défaut de simple-jwt.

#views.py

class MyTokenObtainPairView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer

Et je remplace le sérialiseur comme ci-dessous:

#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

Ainsi, si le client transmet les informations d'identification de l'utilisateur dans l'un des formulaires possibles ci-dessous, je pourrai l'authentifier et renvoyer la paire de jetons.

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

ou

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

Le problème est que lorsque j'envoie des données sous la deuxième forme, j'obtiens 400 BadRequest:password is required. Comment personnaliser les champs et leur validation?

3
Winston

Comme Saiful Azad mentionné dans les commentaires, une méthode possible consiste à utiliser des sérialiseurs séparés pour chacun des scénarios.

#views.py

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

Ensuite, vous pouvez implémenter votre propre sérialiseur pour la vérification otp. J'ai utilisé implémentation de simple-jwt pour implémenter mon propre sérialiseur et utiliser ma méthode d'authentification personnalisée.

1
Winston