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就無法登陸了。

發佈了124 篇原創文章 · 獲贊 4 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章