簡體   English   中英

覆蓋 simple-jwt 的 TokenObtainPairSerializer 來實現 2FA

[英]Overriding simple-jwt's TokenObtainPairSerializer to implement 2FA

我目前正在嘗試在我的 Django 應用程序中實現 2FA。 我所做的第一件事是修改 UserSerializer class 中的Meta UserSerializer以添加兩個字段enabled (指示是否為用戶啟用了 2FA)和secret_key (生成 OTP 的密鑰,當他啟用時共享給用戶2FA)。

為了最大限度地修改登錄流程,我修改了發送來生成訪問令牌的表單,以包含一個新字段“otp”。 用戶可以填寫或者不填寫,后台會檢查用戶是否開啟了2FA,如果開啟了OTP是否正確。

如果沒有 2FA,登錄只是一個帶有 body {"username": usr, "password": pwd}的 POST 請求。 這已成為一個帶有 body {"username": usr, "password": pwd, "otp": otp}的 POST 請求。 如果用戶用戶尚未啟用 2FA,他只需將opt字段留空即可。

我的urls.py看起來像這樣:

path("api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair")

我的想法是重寫 TokenObtainPairView 以適應新的請求。 根據我的發現,我必須更改validate方法,但我真的不知道如何做到這一點。 我可能必須獲取用戶的enabledsecret_key字段的值(基於用戶名)以生成 OTP(如果相關)並對照otp字段進行檢查。 問題是,我不知道該怎么做,而且在 simple-jwt 實現中我有點迷失了。

首先,我不會為您的問題提供完整的解決方案,但這可能是一個好的開始。

創建您的自定義LoginView

class LoginView(TokenObtainPairView):
    serializer_class = LoginSerializer

實現您自己的繼承TokenObtainPairSerializer的序列化程序:

class LoginSerializer(TokenObtainPairSerializer):
    def validate(self, attrs):
        # implement your logic here
        # data = super().validate(attrs)
        return data

更改urls.py

path("api/token/", LoginView.as_view(), name="token_obtain_pair")

這就是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 {}

因此,您可以在自己的序列化程序中實現__init___並添加您的otp字段並在validate方法中實現您想要的邏輯(您可以在此處訪問self.user並檢查他是否啟用了2FA )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM