django使用email进行身份验证(转载)

版权所有,转载请注明出处: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, url

urlpatterns = 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.py

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User

class 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就无法登陆了。

posted @ 2014-10-09 10:08  r3call  阅读(1325)  评论(0编辑  收藏  举报