Django自定义用户电子邮件帐户验证 [英] Django Custom User Email Account Verification

查看:72
本文介绍了Django自定义用户电子邮件帐户验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望在Django中添加电子邮件帐户验证。我曾尝试使用django-registration应用程序执行此操作,但似乎并未对其进行更新以使其与自定义用户模型完全兼容,这会引起太多问题。是否有另一个可靠且有据可查的应用程序可以让我发送有关django中用户注册的验证电子邮件?

I am looking to add email account verification in Django. I have attempted using the django-registration app to do so, but it doesn't appear that it has been updated to be fully compatible with custom user models which causes too many problems. Is there another reliable and well-documented app out there which will allow me to send a verification email on user registration in django?

推荐答案

我如何亲自处理电子邮件注册:

How I handle the email registration personally:

首先全部,我的个人资料扩展了Django用户( models.py ):

First of all, my Profile extending Django Users (models.py):

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 ,注册类:

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 中,我们需要处理所有这些,让我们开始:

Now, in views.py, we need to handle all that, let's go :

注册视图:

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())

激活视图:

#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 中:

url(r'^register/$', 'register'),
url(r'^activate/(?P<key>.+)$', 'activation'),
url(r'^new-activation-link/(?P<user_id>\d+)/$', 'new_activation_link'),

您应该拥有的一切首先,请在.txt电子邮件和HTML中使用适当的模板标签,它应该可以工作。

With all that you should have something to start with, use the appropriate templatetags in the .txt emails and HTML and it should work.

注意:这段代码并不完美,有重复(例如,可以在一个函数中定义随机密钥的生成),但确实可以。另外:激活密钥不是使用适当的加密功能生成的。一种替代方法是使用类似以下的函数来生成密钥:

NB: This code isn't perfect, there is duplication (for instance, the generation of the random key could be defined in a function), but it does the job. Also: the activation key is not generated using proper cryptographic functions. An alternative is to use a function like the following to generate the keys:

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()

NB2:Django send_mail 不提供任何用于验证电子邮件的工具。如果您想验证电子邮件(DKIM,SPF),建议您调查以下内容: https:// djangosnippets .org / snippets / 1995 /

NB2: Django send_mail doesn't provide any tools to authenticate your emails. If you want to authenticate your emails (DKIM, SPF), I advise you to look into this: https://djangosnippets.org/snippets/1995/

NB3:视图new_activation_link存在安全问题:它应检查请求重新发送的用户是否为正确的人,如果还没有通过身份验证的话。我让你纠正。

NB3: There is a security issue with the view new_activation_link: it should check if the user requesting the re-send is the right one and also if he isn't already authenticated. I let you correct that.

这篇关于Django自定义用户电子邮件帐户验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆