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?
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.