📜  django 使用电子邮件进行身份验证 - Python (1)

📅  最后修改于: 2023-12-03 15:14:43.884000             🧑  作者: Mango

Django 使用电子邮件进行身份验证

在Web应用程序中,身份验证是最重要的安全功能之一。Django提供了内置的身份验证系统,可以通过用户名和密码进行认证。然而,有时候我们需要让用户使用他们的电子邮件地址来进行身份验证。

本文将会介绍如何在Django中使用电子邮件地址进行身份验证。

设置

首先,在settings.py文件中,我们需要做出一些更改以允许用户使用电子邮件地址进行身份验证。

AUTHENTICATION_BACKENDS中添加一个EmailBackend类:

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'yourapp.backends.EmailBackend',
)

然后,我们需要定义新的认证后端,例如EmailBackend。在该类中,我们使用get_user方法通过电子邮件地址查询用户:

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model

class EmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

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

注意: 这个后端类需要放在一个自己建立的backend.py文件中

注册用户

当一个用户注册时,我们需要验证电子邮件地址以确保它是唯一的。

为了做到这一点,可以使用Django内置的验证器。 Django中的验证器是独立的序列化组件,提供了一些有用的验证功能,例如邮箱格式、密码复杂度、身份证格式等。

from django.core.validators import validate_email
from django.core.exceptions import ValidationError

class SignupForm(forms.ModelForm):
    def clean_email(self):
        email = self.cleaned_data.get('email')
        if not email:
            raise ValidationError("Email address is required.")
        validate_email(email)
        if User.objects.filter(email=email).exists():
            raise ValidationError("Email address already exists.")
        return email

    class Meta:
        model = User
        fields = ('email', 'password', 'first_name', 'last_name')
        widgets = {'password': forms.PasswordInput}

在这个例子中,我们定义了一个SignupForm类,其中clean_email是验证电子邮件地址的方法。这个方法使用了validate_email验证器,确保电子邮件地址格式正确,然后它检查数据库中是否存在该电子邮件地址。

如果期望您有其他验证需求,您可以添加到这个方法中。

登录用户

现在,我们已经设置了可以通过电子邮件地址进行身份验证的方式,下一步是让用户使用该方法登录。

Django使用django.contrib.auth.views.login视图处理用户登录。 如果要使用电子邮件地址进行身份验证,则需要自定义此视图。

from django.contrib.auth.views import LoginView
from django.urls import reverse_lazy

class EmailLoginView(LoginView):
    template_name = 'yourapp/login.html'
    redirect_authenticated_user = True
    success_url = reverse_lazy('home')
    
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['fields'] = ['email', 'password']
        return kwargs

在这个例子中,我们定义了EmailLoginView视图。 我们使用LoginView视图作为基类,但是我们添加了额外的内容,以便用户可以使用电子邮件地址登录。

我们指定fields列表,该列表仅包括emailpassword字段。

发送验证链接

最后,我们需要确保用户拥有唯一的电子邮件地址,并且拥有该电子邮件地址的用户可以通过该地址进行身份验证。

在用户注册之后,我们可以给用户发送一封包含验证链接的电子邮件。

from django.core.mail import send_mail
from django.template.loader import render_to_string

def send_verification_email(user):
    current_site = Site.objects.get_current()
    subject = 'Verify your email on {0}'.format(current_site.name)
    message = render_to_string('yourapp/emails/verify_email.html', {
        'user': user,
        'domain': current_site.domain,
        'uid': urlsafe_base64_encode(force_bytes(user.pk)),
        'token': default_token_generator.make_token(user),
    })
    send_mail(subject, message, 'from@example.com', [user.email], fail_silently=False)

在这个例子中,我们定义了一个send_verification_email方法,用于发送包含验证链接的电子邮件。

邮件模板中应该包含验证链接:

{% autoescape off %}
To verify your email address, please click on the link below:

http://{{ domain }}/verify-email/{{ uid }}/{{ token }}/

{% endautoescape %}
结论

现在,您已经知道如何使用Django中的电子邮件地址进行身份验证。我们已经实现了一个允许用户使用唯一电子邮件地址进行身份验证的Web应用程序。

authen/urls.py 中自定义的路由

from django.urls import path, include
from .views import EmailLoginView

urlpatterns = [
    path('login/', EmailLoginView.as_view(), name='login'),
    path('verify-email/<uidb64>/<token>/', verify_email, name='verify_email'),
    path('', include('django.contrib.auth.urls')),
]

以上,就是使用Django中的电子邮件地址进行身份验证的所有步骤。