Kin*_*ins 5 python django jwt django-rest-framework multi-factor-authentication
我目前正在尝试在我的 Django 应用程序中实现双因素身份验证。我做的第一件事是修改Meta类中的类UserSerializer以添加两个字段enabled(指示用户是否启用 2FA 的布尔值)和secret_key(生成 OTP 的密钥,当用户启用 2FA 时共享给用户)。
为了最大限度地修改登录流程,我修改了发送以生成访问令牌的表单,以包含新字段“otp”。用户可以填写也可以不填写,后端会检查用户是否启用了2FA,如果是,OTP是否正确。
如果没有 2FA,登录只是一个带有 body 的 POST 请求{"username": usr, "password": pwd}。这已成为带有 body 的 POST 请求{"username": usr, "password": pwd, "otp": otp}。如果用户尚未启用 2FA,他只需将该opt字段留空即可。
我的urls.py看起来像这样:
path("api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair")
Run Code Online (Sandbox Code Playgroud)
我的想法是重写 TokenObtainPairView 以适应新的请求。根据我的发现,我必须改变validate方法,但我真的不知道如何做到这一点。enabled我可能必须获取用户的和字段的值secret_key(基于用户名)来生成 OTP(如果相关)并根据字段进行检查otp。问题是,我不知道该怎么做,而且我在 simple-jwt 实现中有点迷失了。
首先,我不会为您的问题提供完整的解决方案,但这可能是一个好的开始。
创建您的自定义LoginView:
class LoginView(TokenObtainPairView):
serializer_class = LoginSerializer
Run Code Online (Sandbox Code Playgroud)
实现您自己的序列化器,它继承TokenObtainPairSerializer:
class LoginSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
# implement your logic here
# data = super().validate(attrs)
return data
Run Code Online (Sandbox Code Playgroud)
更改url.py
path("api/token/", LoginView.as_view(), name="token_obtain_pair")
Run Code Online (Sandbox Code Playgroud)
这是TokenObtainSerializer的样子:
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 {}
Run Code Online (Sandbox Code Playgroud)
__init___因此,您可以在自己的序列化器中实现并添加您的otp字段并在validate方法内实现您想要的逻辑(您可以在此处访问self.user并检查他是否启用了2FA )。
| 归档时间: |
|
| 查看次数: |
4821 次 |
| 最近记录: |