Django中的电子邮件验证

Posted

技术标签:

【中文标题】Django中的电子邮件验证【英文标题】:Email verification in Django 【发布时间】:2019-08-29 21:29:42 【问题描述】:

我在 Django 中有一个网络应用程序。我尝试使用令牌生成器进行密码重置来创建验证邮件,它没有激活电子邮件。

解决问题:

    当用户提供电子邮件时,它应该检查电子邮件是否存在于数据库中。 (数据库将使用用户电子邮件进行更新) 验证数据库中是否存在电子邮件后,系统会提示用户创建密码。 创建密码后,用户可以登录到相应的页面。

有什么解决办法吗?我尝试并遵循:

https://medium.com/@frfahim/django-registration-with-confirmation-email-bb5da011e4ef

上面的帖子帮助我发送了电子邮件,但验证电子邮件后用户未激活。该帖子不符合我的要求,但我尝试检查是否可以进行电子邮件验证。

是否有任何适用于 Django 的第三方模块或针对我提到的要求的任何解决方案?

【问题讨论】:

【参考方案1】:

我想出了一个解决方案,但是对于第二个要求,用户必须在创建帐户时输入密码。主要目标是验证用户提供的电子邮件。

型号

class Yourmodel(models.Model):
    first_name = models.CharField(max_length=200)
    second_name = models.CharField(max_length=200)
    email = models.EmailField(max_length=100)

代币

from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils import six
class TokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        return (
            six.text_type(user.pk) + six.text_type(timestamp) +
            six.text_type(user.is_active)
        )
account_activation_token = TokenGenerator()

观看次数

from django.contrib.auth import get_user_model
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.contrib.sites.shortcuts import get_current_site
from .tokens import account_activation_token
from django.core.mail import send_mail

def signup(request):
    User = get_user_model()
    if request.method == 'POST':
        form = SignupForm(request.POST)
        if form.is_valid():
            email = form.cleaned_data.get('email')
            if Yourmodel.objects.filter(email__iexact=email).count() == 1:
                user = form.save(commit=False)
                user.is_active = False
                user.save()
                current_site = get_current_site(request)
                mail_subject = 'Activate your account.'
                message = render_to_string('email_template.html', 
                            'user': user,
                            'domain': current_site.domain,
                            'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                            'token': account_activation_token.make_token(user),
                        )
                to_email = form.cleaned_data.get('email')
                send_mail(mail_subject, message, 'youremail', [to_email])
                return HttpResponse('Please confirm your email address to complete the registration')
     else:
        form = SignupForm()
    return render(request, 'regform.html', 'form': form)

def activate(request, uidb64, token):
    User = get_user_model()
    try:
        uid = force_text(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except(TypeError, ValueError, OverflowError, User.DoesNotExist):
        user = None
    if user is not None and account_activation_token.check_token(user, token):
        user.is_active = True
        user.save()
        return HttpResponse('Thank you for your email confirmation. Now you can login your account.')
    else:
        return HttpResponse('Activation link is invalid!')

表格

from django.contrib.auth.forms import UserCreationForm


class SignupForm(UserCreationForm):
    class Meta:
        model = User
        fields = ('username', 'email', 'password1', 'password2')

电子邮件模板

% autoescape off %
Hi ,
Please click on the link to confirm your registration,
http:// domain % url 'activate' uidb64=uid token=token %
% endautoescape %

regform.html

% csrf_token %
% for field in form %
<label > field.label_tag </label>
 field 
% endfor %

如果您不想与模型中的电子邮件地址进行比较,您可以 跳过,这会将电子邮件发送到提供的电子邮件地址 在注册时无需进一步验证。

email = form.cleaned_data.get('email')
if Yourmodel.objects.filter(email__iexact=email).count() == 1:

【讨论】:

为什么哈希的字符串选择不同于Django auth's 内置default_token_generator,它们使用pk、密码、login_timestamp、时间戳和电子邮件。更改它会降低安全性吗? 你从哪里得到 force_byte,而我无法从 django utils 导入六个 @nassim ***.com/questions/59193514/… @nassim 顺便说一句,force_bytes 很可能来自from django.utils.encoding import force_bytes【参考方案2】:

我对你的第一个问题有一个答案:

如果您基于 PasswordResetView + PasswordResetConfirmView 重置用户密码,您可以执行以下操作:

PasswordResetView 负责向用户发送电子邮件。它使用自己的表单来输入用户电子邮件 -PasswordResetForm。您可以制作自己的表单并从 PasswordResetForm 继承它。 例如:


class PRForm(PasswordResetForm):
    def clean_email(self):
        email = self.cleaned_data['email']
        if not User.objects.filter(email__iexact=email, is_active=True).exists():
            msg = "There is no user with this email."
            self.add_error('email', msg)
        return email

# User – your user model or any custom model if you have one instead of the default one

此代码将不允许控制器向您的数据库中没有的电子邮件地址发送电子邮件。

然后在您的 VIEW 中指定此表单:


class PassResView(RatelimitMixin,  PasswordResetView):
    success_url = 
    from_email = 
    subject_template_name =
    email_template_name =
    success_message = 
    template_name = 
    form_class = PRForm  # here is a custom form
    ratelimit_key = 'ip'
    ratelimit_rate = '10/5m'
    ratelimit_block = True
    ratelimit_method = ('GET', 'POST')

RatelimitMixin 不允许有人通过运行您的 BD 来暴力破解您的数据库。你可以使用它或不使用它 - 这取决于你。

【讨论】:

考虑我的电子邮件地址存在于模型类 Test(models.Model): first_name = models.CharField(max_length=200) email_address = models.CharField(max_length=200) ,我想检查一下这个电子邮件地址并发送电子邮件 如果不是 Test.objects.filter(email_address__iexact=email, is_active=True).exists(): 还有一个疑问,你提到的代码,我应该在视图或表单中的什么地方使用它?? 你最好阅读有关 PasswordResetView 的 Django 文档并从那里开始【参考方案3】:

对于第一个答案,您需要添加 urls.py

path('emailVerification/<uidb64>/<token>', views.activate, name='emailActivate')

emailVerification.html必须是这样的:

    Hi ,
Please click on the link to confirm your registration,
http:// domain /emailVerification/ uid / token 

【讨论】:

以上是关于Django中的电子邮件验证的主要内容,如果未能解决你的问题,请参考以下文章

Django 自定义用户电子邮件帐户验证

django 完成邮件验证

Django中电子邮件验证的实现

表单验证 - Django 中的注册和登录错误处理

验证 Django 中是不是存在电子邮件 [重复]

Django - 身份验证,使用电子邮件确认注册