django使用email进行身份验证

来源:互联网 发布:mac软件卸载不掉 编辑:程序博客网 时间:2024/05/17 07:49

版权所有,转载请注明出处:http://guangboo.org/2013/03/27/authentication-using-email-in-django

django自带的验证功能免去了我们的大量工作,它提供了验证、授权相关的接口,我们只有非常少的代码就可以实现,但是django自带的身份验证的方法只能使用用户名来进行验证,如果要想使用email进行验证的话,就需要自己编写一些代码了。

为使得我们能在使用django提供的验证功能时,能够使用email进行身份验证,本文提出一个简单的解决方案,使尽量少的编写代码,同时又能实现上面的功能。本文使用环境django(1.4.2)+python(2.7.3)。

django的身份验证授权等功能在模块django.contrib.auth模块下,该模块下提供了默认的验证表单,修改密码,找回密码等表单,验证,登录接口等。其中views.py下提供了login和logout方法,用户登录和注销,当然还包含其他的如登录跳转,重置密码,修改密码等。这些view方法都有很多的参数,都是为了扩展而添加的,这些方法我们可以直接拿来使用,如果我们不考虑email验证或登录界面的话,就可以使用如下代码:

from django.conf.urls import patterns, include, urlurlpatterns = patterns('',    url(r'^login/$', 'django.contrib.auth.views.login', name = 'login'),)

只要将上面的三行代码拷贝到urls.py文件中,就可以实现login的功能,只是登录界面是admin的登录界面,并且使用默认的用户名和密码进行验证。如果我们查看django.contrib.auth.views.login方法的源代码的话,就会发现login的方法签名为:

def login(request, template_name='registration/login.html',          redirect_field_name=REDIRECT_FIELD_NAME,          authentication_form=AuthenticationForm,          current_app=None, extra_context=None)

login方法有很多参数,并且都是有默认值的,对我们来说,最常用的就是template_name参数了,我们可以这样修改urls.py文件,实现登录界面的自定义。

urlpatterns = patterns('',    url(r'^login/$', 'django.contrib.auth.views.login', {'template_name':'account/long.html'}, name = 'login'),)

与前面的代码比较,在url方法中添加了一个参数 {'template_name':'account/long.html'},该参数就会传递给login方法,从而就实现修改登录界面的目的了。也许你会疑惑,为什么login方法中为什么没有身份验证的代码,其实身份验证的功能是实现在form中的,就是默认的身份验证表单AuthenticationForm,我们继续阅读AuthenticationForm表单的源代码:django.contrib.auth.forms.AuthenticationForm,我们会发现身份验证功能的实现,是在方法clean中,代码如下:

def clean(self):        username = self.cleaned_data.get('username')        password = self.cleaned_data.get('password')        if username and password:            self.user_cache = authenticate(username=username,                                           password=password)            if self.user_cache is None:                raise forms.ValidationError(                    self.error_messages['invalid_login'])            elif not self.user_cache.is_active:                raise forms.ValidationError(self.error_messages['inactive'])        self.check_for_test_cookie()        return self.cleaned_data

其中authenticate方法就是我们要找的验证代码,当然到此我们已经找到验证的实现,我们就可以重写一个验证表单,重新实现clean方法就可以实现我们自己的验证方式--使用email验证,然后在

{'template_name':'account/long.html'}参数中添加自定义的验证表单类,如:

urlpatterns = patterns('',    url(r'^login/$', 'django.contrib.auth.views.login', {'template_name':'account/long.html','authentication_form':CustomAuthForm}, name = 'login'),)

其中CustomAuthForm是我们自定义的验证表单,我们可以参考django自动的AuthenticationForm的实现编写我们自己的CustomAuthForm类,这里就不在给出实例,这是一种方法。

另一种方法,我们定义一个backend类,如下:

# -*- coding:utf-8 -*-# backends.pyfrom django.contrib.auth.backends import ModelBackendfrom django.contrib.auth.models import Userclass EmailCheckModelBackend(ModelBackend):    def authenticate(self, username = None, password = None, is_staff = None):        try:            user = User.objects.get(email = username)            if user.check_password(password):                if is_staff is not None:                    if user.is_staff == is_staff:                        return user                    else:                        return None                return user                    except User.DoesNotExist:            return None

并且在settings.py文件中添加如下代码即可:

AUTHENTICATION_BACKENDS = ('account.backends.EmailCheckModelBackend',)

需要说明的是,authenticate方法签名中的原有参数名称最后不要修改,因为admin的验证方式也会使用该backed,如果你仔细观察AuthenticationForm的clean方法的话,authenticate方法调用是传递了参数名的,如果我们将username参数名该成了email或者其他名称的话,admin就无法登陆了。