Django身份验证在现有应用中同时使用电子邮件和用户名

huangapple go评论65阅读模式
英文:

Django Authentication to use both email and username in exiting app

问题

我在现有应用程序中添加自定义AUTHENTICATION_BACKENDS方面遇到了困难。我已经完成了我的应用程序,但现在希望能够使用用户名或电子邮件ID进行登录。我已经成功地能够使用用户名和密码进行登录。现在我想添加电子邮件ID。

我尝试在我的settings.py中添加以下代码:

AUTHENTICATION_BACKENDS = (
    'authentication.backends.EmailOrUsernameModelBackend',
    'django.contrib.auth.backends.ModelBackend',
)

在authentication/backends.py中,我有以下代码:

from django.conf import settings
from django.contrib.auth.models import User

class EmailOrUsernameModelBackend(object):
    def authenticate(self, username=None, password=None):
        print("Inside EmailorUsernameModelBackend")
        if '@' in username:
            print("User with Email")
            kwargs = {'email': username}
        else:
            print("User with Username")
            kwargs = {'username': username}
        try:
            user = User.objects.get(**kwargs)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

我的authentication/views.py如下:

def login_view(request):
    form = LoginForm(request.POST or None)

    msg = None

    if request.method == "POST":

        if form.is valid():
            username = form.cleaned_data.get("username")
            password = form.cleaned_data.get("password")
            user = authenticate(username=username, password=password)
            print("User=", user)
            if user is not None:
                login(request, user)
                return redirect("dashboard")
            else:
                msg = 'Invalid credentials'
        else:
            msg = 'Error validating the form'

    return render(request, "/login.html", {"form": form, "msg": msg})

我尝试在EmailOrUsernameModelBackend的authenticate方法中打印一些语句,但没有输出,所以我猜想由于某种原因它没有调用该方法。

请帮助我弄清楚我漏掉了什么,以便调用自定义authenticate方法。

英文:

I am struggling with adding custom AUTHENTICATION_BACKENDS for my exiting app. I have all done with my app but now want to login with username or EmailID. I am successfully able to login with username and password.
now just want to add EmailID as well.

I tried adding below code in my settings.py
AUTHENTICATION_BACKENDS = (
'authentication.backends.EmailOrUsernameModelBackend',
'django.contrib.auth.backends.ModelBackend', )

and in \authentication\backends.py I have

from django.conf import settings
from django.contrib.auth.models import User

class EmailOrUsernameModelBackend(object):
    def authenticate(self, username=None, password=None):
        print("Inside EmailorUsernameModelBackend")
        if '@' in username:
            print("User with Email")
            kwargs = {'email': username}
        else:
            print("User with Username")
            kwargs = {'username': username}
        try:
            user = User.objects.get(**kwargs)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

where my \authentication\views.py

def login_view(request):
    form = LoginForm(request.POST or None)

    msg = None

    if request.method == "POST":

        if form.is_valid():
            username = form.cleaned_data.get("username")
            password = form.cleaned_data.get("password")
            user = authenticate(username=username, password=password)
            print("User=",user)
            if user is not None:
                login(request, user)
                return redirect("dashboard")
            else:
                msg = 'Invalid credentials'
        else:
            msg = 'Error validating the form'

    return render(request, "/login.html", {"form": form, "msg": msg})

I am trying to print some statement if authenticate method call from EmailOrUsernameModelBackend but none printing, so I guess for some reason it is not calling that method.

please help me what I am missing to call custom authenticate method.

答案1

得分: 0

我认为问题在于您没有从Django中的BaseBackend进行子类化,而只是从常规的Python object 进行子类化。
通常我会创建两个独立的后端,这样我的代码对其他人来说更容易阅读。

from django.contrib.auth.backends import BaseBackend

class EmailBackend(BaseBackend):
    def authenticate(self, request, username=None, password=None):
        try:
            user = User.objects.get(email=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None

class UsernameBackend(BaseBackend):
    def authenticate(self, request, username=None, password=None):
        try:
            user = User.objects.get(username=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None
英文:

I think the issue is that you're not subclassing BaseBackend from Django, but just the regular python object.
I usually do 2 seperate backends, that makes my code a lot clearer to read for others.

from django.contrib.auth.backends import BaseBackend

class EmailBackend(BaseBackend):
    def authenticate(self, request, username=None, password=None):
        try:
            user = User.objects.get(email=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None


class UsernameBackend(BaseBackend):
    def authenticate(self, request, username=None, password=None):
        try:
            user = User.objects.get(username=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None

huangapple
  • 本文由 发表于 2023年2月18日 02:42:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75488183.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定