实现无密码djangorestframework-simplejwt令牌认证
Implement djangorestframework-simplejwt token authentication without password
我的应用程序不需要密码,因为我想使用 phone 和 OTP 登录。
我正在尝试实现自定义的简单 JWT 令牌身份验证,它只需要一个 phone 号码而不需要密码。
我是 Django 的新手,我确实检查了 Whosebug 中的一些链接并尝试了这个:
class CustomSerializer(TokenObtainPairSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields[self.username_field] = serializers.CharField()
del self.fields['password']
def validate(self,attr):
print(attr)
data = super().validate(attr)
token = self.get_token(self.user)
print (token)
try:
request = self.context["request"]
print(request)
except KeyError:
pass
request_data = json.loads(request.body)
print(request_data)
所以这里当执行验证方法时,它会去验证 TokenObtainPairSerializer
init 方法,在 return 中调用它的父 class 的 init 方法来验证密码。
因此,即使我删除了自定义序列化程序中的密码字段,它仍然会给我一个密码键错误。
我试图通过密钥错误,但它再次在 request.body
.
处失败
我卡在这上面了,我不知道如何实现没有密码的简单 JWT。
我有同样的问题,经过大量搜索和阅读 django-rest-framework-simplejwt 的源代码后,我得到了答案。
So even if i am deleting passowrd field in my custom serializer, it still give me key-error of password
如果你看一下TokenObtainSerializer
class,它是TokenObtainPairSerializer
here的父Serializer,你可以看到密码是这样调用的:
# rest_framework_simplejwt/serializers.py
def validate(self, attrs):
authenticate_kwargs = {
self.username_field: attrs[self.username_field],
'password': attrs['password'],
}
# ...
因此即使您删除了密码字段,稍后仍会调用它。
我所做的是将密码字段设置为不需要,并指定一个空字符串作为密码。
class TokenObtainPairWithoutPasswordSerializer(TokenObtainPairSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['password'].required = False
def validate(self, attrs):
attrs.update({'password': ''})
return super(TokenObtainPairWithoutPasswordSerializer, self).validate(attrs)
现在可以在视图中使用此序列化程序。
class TokenObtainPairWithoutPasswordView(TokenViewBase):
serializer_class = TokenObtainPairWithoutPasswordSerializer
然后我创建了一个自定义身份验证后端,这样用户就可以在没有密码的情况下进行身份验证。
from django.contrib.auth.backends import BaseBackend
class AuthenticationWithoutPassword(BaseBackend):
def authenticate(self, request, username=None):
if username is None:
username = request.data.get('username', '')
try:
return User.objects.get(username=username)
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
您可以阅读 docs 以获取有关创建自定义身份验证后端的更多信息。
最后,在 settings.py
更改您的 AUTHENTICATION_BACKENDS
变量。
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'core.custom_authentication.AuthenticationWithoutPassword',
)
现在 Django 将尝试使用第一个身份验证 ModelBackend
进行身份验证,然后是新的 AuthenticationWithoutPassword
.
这里只是说显而易见的,但请记住,没有密码的身份验证肯定是不安全的,所以你应该在你的自定义身份验证中添加更多的逻辑,记住你可以访问request
变量。
我的应用程序不需要密码,因为我想使用 phone 和 OTP 登录。 我正在尝试实现自定义的简单 JWT 令牌身份验证,它只需要一个 phone 号码而不需要密码。 我是 Django 的新手,我确实检查了 Whosebug 中的一些链接并尝试了这个:
class CustomSerializer(TokenObtainPairSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields[self.username_field] = serializers.CharField()
del self.fields['password']
def validate(self,attr):
print(attr)
data = super().validate(attr)
token = self.get_token(self.user)
print (token)
try:
request = self.context["request"]
print(request)
except KeyError:
pass
request_data = json.loads(request.body)
print(request_data)
所以这里当执行验证方法时,它会去验证 TokenObtainPairSerializer
init 方法,在 return 中调用它的父 class 的 init 方法来验证密码。
因此,即使我删除了自定义序列化程序中的密码字段,它仍然会给我一个密码键错误。
我试图通过密钥错误,但它再次在 request.body
.
我卡在这上面了,我不知道如何实现没有密码的简单 JWT。
我有同样的问题,经过大量搜索和阅读 django-rest-framework-simplejwt 的源代码后,我得到了答案。
So even if i am deleting passowrd field in my custom serializer, it still give me key-error of password
如果你看一下TokenObtainSerializer
class,它是TokenObtainPairSerializer
here的父Serializer,你可以看到密码是这样调用的:
# rest_framework_simplejwt/serializers.py
def validate(self, attrs):
authenticate_kwargs = {
self.username_field: attrs[self.username_field],
'password': attrs['password'],
}
# ...
因此即使您删除了密码字段,稍后仍会调用它。
我所做的是将密码字段设置为不需要,并指定一个空字符串作为密码。
class TokenObtainPairWithoutPasswordSerializer(TokenObtainPairSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['password'].required = False
def validate(self, attrs):
attrs.update({'password': ''})
return super(TokenObtainPairWithoutPasswordSerializer, self).validate(attrs)
现在可以在视图中使用此序列化程序。
class TokenObtainPairWithoutPasswordView(TokenViewBase):
serializer_class = TokenObtainPairWithoutPasswordSerializer
然后我创建了一个自定义身份验证后端,这样用户就可以在没有密码的情况下进行身份验证。
from django.contrib.auth.backends import BaseBackend
class AuthenticationWithoutPassword(BaseBackend):
def authenticate(self, request, username=None):
if username is None:
username = request.data.get('username', '')
try:
return User.objects.get(username=username)
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
您可以阅读 docs 以获取有关创建自定义身份验证后端的更多信息。
最后,在 settings.py
更改您的 AUTHENTICATION_BACKENDS
变量。
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'core.custom_authentication.AuthenticationWithoutPassword',
)
现在 Django 将尝试使用第一个身份验证 ModelBackend
进行身份验证,然后是新的 AuthenticationWithoutPassword
.
这里只是说显而易见的,但请记住,没有密码的身份验证肯定是不安全的,所以你应该在你的自定义身份验证中添加更多的逻辑,记住你可以访问request
变量。