Python 覆盖简单的jwt';s TokenActainPairSerializer以实现2FA
我目前正试图在Django应用程序中实现2FA。我做的第一件事是修改Python 覆盖简单的jwt';s TokenActainPairSerializer以实现2FA,python,django,django-rest-framework,jwt,Python,Django,Django Rest Framework,Jwt,我目前正试图在Django应用程序中实现2FA。我做的第一件事是修改UserSerializer类中的Meta类,以添加两个字段enabled(指示是否为用户启用了2FA)和secret\u key(生成OTP的密钥,当用户启用2FA时,该密钥将共享给用户) 为了尽可能少地修改登录流,我修改了用于生成访问令牌的表单,以包含一个新字段“otp”。用户可以填写或不填写,后端将检查用户是否启用了2FA,如果是,则检查OTP是否正确 如果没有2FA,登录只不过是一个POST请求,其正文{“usernam
UserSerializer
类中的Meta
类,以添加两个字段enabled
(指示是否为用户启用了2FA)和secret\u key
(生成OTP的密钥,当用户启用2FA时,该密钥将共享给用户)
为了尽可能少地修改登录流,我修改了用于生成访问令牌的表单,以包含一个新字段“otp”。用户可以填写或不填写,后端将检查用户是否启用了2FA,如果是,则检查OTP是否正确
如果没有2FA,登录只不过是一个POST请求,其正文{“username”:usr,“password”:pwd}
。这已成为一个POST请求,其正文{“username”:usr,“password”:pwd,“otp”:otp}
。如果用户没有启用2FA,他只需将opt
字段留空即可
我的url.py
如下所示:
path("api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair")
我的想法是覆盖TokenGetPairView以适应新的请求。根据我的发现,我必须更改
validate
方法,但我真的不知道该怎么做。我可能需要获取用户的enabled
和secret\u key
字段的值(基于用户名)来生成OTP(如果相关),并对照OTP
字段进行检查。问题是,我不知道怎么做,我在简单的jwt实现中有点迷失了方向。首先,我不会为您的问题提供完整的解决方案,但这可能是一个好的开始
创建自定义的登录视图:
class LoginView(TokenObtainPairView):
serializer_class = LoginSerializer
class LoginSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
# implement your logic here
# data = super().validate(attrs)
return data
实现您自己的序列化程序,该序列化程序继承TokenActainPairSerializer:
class LoginView(TokenObtainPairView):
serializer_class = LoginSerializer
class LoginSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
# implement your logic here
# data = super().validate(attrs)
return data
更改URL.py
path("api/token/", LoginView.as_view(), name="token_obtain_pair")
这就是令牌获取序列化程序的外观:
class TokenObtainSerializer(serializers.Serializer):
username_field = User.USERNAME_FIELD
default_error_messages = {
'no_active_account': _('No active account found with the given credentials')
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields[self.username_field] = serializers.CharField()
self.fields['password'] = PasswordField()
def validate(self, attrs):
authenticate_kwargs = {
self.username_field: attrs[self.username_field],
'password': attrs['password'],
}
try:
authenticate_kwargs['request'] = self.context['request']
except KeyError:
pass
self.user = authenticate(**authenticate_kwargs)
if not getattr(login_rule, user_eligible_for_login)(self.user):
raise exceptions.AuthenticationFailed(
self.error_messages['no_active_account'],
'no_active_account',
)
return {}
因此,您可以在自己的序列化程序中实现\uuuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu