首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Django自定义用户邮箱帐号验证

Django自定义用户邮箱帐号验证
EN

Stack Overflow用户
提问于 2014-07-24 21:35:19
回答 2查看 34.8K关注 0票数 39

我希望在Django添加电子邮件帐户验证。我尝试过使用django注册应用来做这件事,但它似乎没有被更新为与自定义用户模型完全兼容,这导致了太多的问题。有没有其他可靠的、文档齐全的应用程序可以让我在django中发送用户注册的验证电子邮件?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-24 22:42:07

我个人如何处理电子邮件注册:

首先,我的简介扩展了Django用户(models.py):

代码语言:javascript
复制
class Profile(models.Model):
    user = models.OneToOneField(User, related_name='profile') #1 to 1 link with Django User
    activation_key = models.CharField(max_length=40)
    key_expires = models.DateTimeField()

forms.py中,注册类:

代码语言:javascript
复制
class RegistrationForm(forms.Form):
    username = forms.CharField(label="",widget=forms.TextInput(attrs={'placeholder': 'Nom d\'utilisateur','class':'form-control input-perso'}),max_length=30,min_length=3,validators=[isValidUsername, validators.validate_slug])
    email = forms.EmailField(label="",widget=forms.EmailInput(attrs={'placeholder': 'Email','class':'form-control input-perso'}),max_length=100,error_messages={'invalid': ("Email invalide.")},validators=[isValidEmail])
    password1 = forms.CharField(label="",max_length=50,min_length=6,
                                widget=forms.PasswordInput(attrs={'placeholder': 'Mot de passe','class':'form-control input-perso'}))
    password2 = forms.CharField(label="",max_length=50,min_length=6,
                                widget=forms.PasswordInput(attrs={'placeholder': 'Confirmer mot de passe','class':'form-control input-perso'}))

    #recaptcha = ReCaptchaField()

    #Override clean method to check password match
    def clean(self):
        password1 = self.cleaned_data.get('password1')
        password2 = self.cleaned_data.get('password2')

        if password1 and password1 != password2:
            self._errors['password2'] = ErrorList([u"Le mot de passe ne correspond pas."])

        return self.cleaned_data

    #Override of save method for saving both User and Profile objects
    def save(self, datas):
        u = User.objects.create_user(datas['username'],
                                     datas['email'],
                                     datas['password1'])
        u.is_active = False
        u.save()
        profile=Profile()
        profile.user=u
        profile.activation_key=datas['activation_key']
        profile.key_expires=datetime.datetime.strftime(datetime.datetime.now() + datetime.timedelta(days=2), "%Y-%m-%d %H:%M:%S")
        profile.save()
        return u

    #Sending activation email ------>>>!! Warning : Domain name is hardcoded below !!<<<------
    #The email is written in a text file (it contains templatetags which are populated by the method below)
    def sendEmail(self, datas):
        link="http://yourdomain.com/activate/"+datas['activation_key']
        c=Context({'activation_link':link,'username':datas['username']})
        f = open(MEDIA_ROOT+datas['email_path'], 'r')
        t = Template(f.read())
        f.close()
        message=t.render(c)
        #print unicode(message).encode('utf8')
        send_mail(datas['email_subject'], message, 'yourdomain <no-reply@yourdomain.com>', [datas['email']], fail_silently=False)

现在,在views.py中,我们需要处理所有这些,让我们开始:

寄存器视图:

代码语言:javascript
复制
def register(request):
    if request.user.is_authenticated():
        return redirect(home)
    registration_form = RegistrationForm()
    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            datas={}
            datas['username']=form.cleaned_data['username']
            datas['email']=form.cleaned_data['email']
            datas['password1']=form.cleaned_data['password1']

            #We generate a random activation key
            salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
            usernamesalt = datas['username']
            if isinstance(usernamesalt, unicode):
                usernamesalt = usernamesalt.encode('utf8')
            datas['activation_key']= hashlib.sha1(salt+usernamesalt).hexdigest()

            datas['email_path']="/ActivationEmail.txt"
            datas['email_subject']="Activation de votre compte yourdomain"

            form.sendEmail(datas)
            form.save(datas) #Save the user and his profile

            request.session['registered']=True #For display purposes
            return redirect(home)
        else:
            registration_form = form #Display form with error messages (incorrect fields, etc)
    return render(request, 'siteApp/register.html', locals())

激活视图:

代码语言:javascript
复制
#View called from activation email. Activate user if link didn't expire (48h default), or offer to
#send a second link if the first expired.
def activation(request, key):
    activation_expired = False
    already_active = False
    profile = get_object_or_404(Profile, activation_key=key)
    if profile.user.is_active == False:
        if timezone.now() > profile.key_expires:
            activation_expired = True #Display: offer the user to send a new activation link
            id_user = profile.user.id
        else: #Activation successful
            profile.user.is_active = True
            profile.user.save()

    #If user is already active, simply display error message
    else:
        already_active = True #Display : error message
    return render(request, 'siteApp/activation.html', locals())

def new_activation_link(request, user_id):
    form = RegistrationForm()
    datas={}
    user = User.objects.get(id=user_id)
    if user is not None and not user.is_active:
        datas['username']=user.username
        datas['email']=user.email
        datas['email_path']="/ResendEmail.txt"
        datas['email_subject']="Nouveau lien d'activation yourdomain"

        salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
        usernamesalt = datas['username']
        if isinstance(usernamesalt, unicode):
            usernamesalt = usernamesalt.encode('utf8')
        datas['activation_key']= hashlib.sha1(salt+usernamesalt).hexdigest()

        profile = Profile.objects.get(user=user)
        profile.activation_key = datas['activation_key']
        profile.key_expires = datetime.datetime.strftime(datetime.datetime.now() + datetime.timedelta(days=2), "%Y-%m-%d %H:%M:%S")
        profile.save()

        form.sendEmail(datas)
        request.session['new_link']=True #Display: new link sent

    return redirect(home)

最后,在urls.py

代码语言:javascript
复制
url(r'^register/$', 'register'),
url(r'^activate/(?P<key>.+)$', 'activation'),
url(r'^new-activation-link/(?P<user_id>\d+)/$', 'new_activation_link'),

有了所有这些,你应该有了一些开始,在.txt电子邮件和超文本标记语言中使用适当的模板标签,它应该可以工作。

注意:这段代码并不完美,存在重复(例如,随机密钥的生成可以在函数中定义),但它可以完成工作。另外:激活密钥不是使用适当的加密函数生成的。另一种方法是使用如下所示的函数生成密钥:

代码语言:javascript
复制
from django.utils.crypto import get_random_string

def generate_activation_key(username):
    chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
    secret_key = get_random_string(20, chars)
    return hashlib.sha256((secret_key + username).encode('utf-8')).hexdigest()

Django :Django send_mail没有提供任何工具来验证你的电子邮件。如果您想验证您的电子邮件(DKIM,SPF),我建议您查看以下内容:https://djangosnippets.org/snippets/1995/

NB3:视图new_activation_link有一个安全问题:它应该检查请求重新发送的用户是否正确,以及他是否还没有经过身份验证。我让你改正这个错误。

票数 65
EN

Stack Overflow用户

发布于 2017-02-15 07:48:34

您可能还会对简单但功能强大的django-verified-email-field感兴趣。

只需在表单中使用VerifiedEmailField

代码语言:javascript
复制
from django import forms
from verified_email_field.forms import VerifiedEmailField

class RegistrationForm(forms.ModelForm):
    email = VerifiedEmailField(label='email', required=True)

或者在你的模型中:

代码语言:javascript
复制
from django.db import models
from verified_email_field.models import VerifiedEmailField

class User(models.Model):
    email = VerifiedEmailField('e-mail')

它呈现两个输入字段:e-mailverification code。验证码使用AJAX发送到电子邮件地址,如果给定的电子邮件没有有效的代码,则在字段的clean期间发送验证码,因此即使没有javascript也可以工作。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24935271

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档