是否有可能在 Django 自定义身份验证中要求密码设置条件?

Any Possibility to put condition on Password Required in Django Custom Auth?

我要注册用户先用邮箱或Phone号码和密码登录。如果用户忘记了密码,那么应该有可能绕过用户 Phone 号码通过 SMS 提供的密码使用 OTP 登录。那么有没有可能实现呢?

Here are official docs where the password field is always required. https://docs.djangoproject.com/en/4.0/topics/auth/customizing/#a-full-example I know we can change the username to the email or for a phone number if we want but how do we put the condition to login with Password/Random OTP. So how we can achieve that? a suggestion would be appreciated. Thanks

是的,我们可以使用强制登录来做到这一点,这是我如何做到这一点的一个例子,请看一下我有一个与用户一对一关系的配置文件

def login_otp(request):
    mobile = request.session['mobile']
    context = {'mobile':mobile}
    if request.method == 'POST':
        otp = request.POST.get('otp')
        profile = Profile.objects.filter(mobile=mobile).first()
        
        if otp == profile.otp:
            user = User.objects.get(id = profile.user.id)
            login(request , user)
            return redirect('cart')
        else:
            context = {'message' : 'Wrong OTP' , 'class' : 'danger','mobile':mobile }
            return render(request,'login_otp.html' , context)
    
    return render(request,'login_otp.html' , context)

您可以将自己的CustomLoginBackend设为

from django.contrib.auth import get_user_model

class CustomLoginBackend(object):

    def authenticate(self, request, email, password, otp):
        User = get_user_model()
        try:
            user = User.objects.using(db_name).get(email=email)
        except User.DoesNotExist:
            return None
        else:
            if password is not None:
                if getattr(user, 'is_active', False) and  user.check_password(password):
                    return user
            else:
                if getattr(user, 'is_active', False) and  user.otp == otp: #<-- otp included in user table
                   return user
        return None

然后在您的 login 观看次数中。

from django.contrib.auth import authenticate, login
from django.contrib import messages

def login_view(request):
    if request.method == 'POST':
        email = request.POST.get('email', None)
        password = request.POST.get('password', None)
        otp = request.POST.get('otp', None)

        user = authenticate(request, email=email, password=password, otp=otp)
        
        if user is not None:
            login(request, user)
            # redirect to a success page
            return redirect('dashboard')
        else:
            if password is not None:
                # return either email or password incorrect
                messages.error(request, "Invalid Email or Password")
                return redirect('login')
            else:
                # return invalid otp
                messages.error(request, "Invalid OTP")
                return redirect('login')

        return render(request, 'login.html')

最后别忘了在 settings.py 中添加 AUTHENTICATION_BACKENDS 作为

AUTHENTICATION_BACKENDS = ['path_to_your.CustomLoginBackend ',]