鍍金池/ 教程/ Python/ 使用Django認證系統(tǒng)
點擊劫持保護
安全問題歸檔
Model 類參考
將遺留數(shù)據(jù)庫整合到Django
關(guān)聯(lián)對象參考
內(nèi)建基于類的視圖的API
聚合
Django 中的用戶認證
django.contrib.humanize
Django管理文檔生成器
分頁
使用Django輸出CSV
加密簽名
文件儲存API
安全
Django中的測試
國際化和本地化
為Django編寫首個補丁
條件表達式
日志
模型元選項
部署靜態(tài)文件
執(zhí)行查詢
使用Django認證系統(tǒng)
基于類的視圖
中間件
編寫自定義的django-admin命令
Django 的設(shè)置
格式本地化
數(shù)據(jù)庫訪問優(yōu)化
錯誤報告
基于類的內(nèi)建通用視圖
編寫自定義存儲系統(tǒng)
編寫你的第一個 Django 程序 第3部分
編寫數(shù)據(jù)庫遷移
使用表單
編寫你的第一個 Django 程序 第2部分
編寫你的第一個 Django 程序 第1部分
如何使用會話
系統(tǒng)檢查框架
新手入門
信號
編寫視圖
如何使用WSGI 部署
編寫你的第一個Django應(yīng)用,第6部分
常見的網(wǎng)站應(yīng)用工具
Widgets
內(nèi)建的視圖
模型實例參考
視圖層
Django中的密碼管理
高級教程:如何編寫可重用的應(yīng)用
國際化和本地化
"本地特色"附加功能
TemplateResponse 和 SimpleTemplateResponse
模式編輯器
文件上傳
快速安裝指南
部署 Django
表單 API
表單素材 ( <code>Media</code> 類)
管理文件
其它核心功能
查找 API 參考
表單
Admin
數(shù)據(jù)庫函數(shù)
自定義查找
使用基于類的視圖處理表單
管理操作
開發(fā)過程
編寫你的第一個Django應(yīng)用,第5部分
進行原始的sql查詢
模型層
多數(shù)據(jù)庫
編寫你的第一個 Django 程序 第4部分
Django安全
Django 初探
Django異常
重定向應(yīng)用
按需內(nèi)容處理
管理器
視圖裝飾器
驗證器
使用Django輸出PDF
File對象
Django 的快捷函數(shù)
基于類的通用視圖 —— 索引
為模型提供初始數(shù)據(jù)
模板層
URL調(diào)度器
中間件
模型

使用Django認證系統(tǒng)

這篇文檔解釋默認配置下Django認證系統(tǒng)的使用。這些配置已經(jīng)逐步可以滿足大部分常見項目對的需要,可以處理范圍非常廣泛的任務(wù),且具有一套細致的密碼和權(quán)限實現(xiàn)。對于需要與默認配置不同需求的項目,Django支持擴展和自定義認證。

Django的認證同時提供認證和授權(quán),并通常統(tǒng)一稱為認證系統(tǒng),因為這些功能某些地方是耦合的。

User對象

[User](../../ref/contrib/auth.html#django.contrib.auth.models.User )對象是認證系統(tǒng)的核心。它們通常表示與你的站點進行交互的用戶,并用于啟用限制訪問、注冊用戶信息和關(guān)聯(lián)內(nèi)容給創(chuàng)建者等。在Django的認證框架中只存在一種類型的用戶,因此諸如['superusers'](../../ref/contrib/auth.html#django.contrib.auth.models.User.is_superuser )或管理員['staff'](../../ref/contrib/auth.html#django.contrib.auth.models.User.is_staff )用戶只是具有特殊屬性集的user對象,而不是不同類型的user對象。

默認user的基本屬性有:

  • [username](../../ref/contrib/auth.html#django.contrib.auth.models.User.username )
  • [password](../../ref/contrib/auth.html#django.contrib.auth.models.User.password )
  • [email](../../ref/contrib/auth.html#django.contrib.auth.models.User.email )
  • [first_name](../../ref/contrib/auth.html#django.contrib.auth.models.User.first_name )
  • [last_name](../../ref/contrib/auth.html#django.contrib.auth.models.User.last_name )

完整的參考請參閱[full API documentation](../../ref/contrib/auth.html#django.contrib.auth.models.User ),該文檔更偏重特定的任務(wù)。

創(chuàng)建users

創(chuàng)建users最直接的方法是使用[create_user()](../../ref/contrib/auth.html#django.contrib.auth.models.UserManager.create_user )輔助函數(shù):

>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')

# At this point, user is a User object that has already been saved
# to the database. You can continue to change its attributes
# if you want to change other fields.
>>> user.last_name = 'Lennon'
>>> user.save()

如果你已經(jīng)安裝了Django admin,你也可以間接地創(chuàng)建users.

創(chuàng)建superusers

使用createsuperuser命令創(chuàng)建superusers:

$ python manage.py createsuperuser --username=joe --email=joe@example.com

將會提示你輸入一個密碼。在你輸入一個密碼后,該user將會立即創(chuàng)建。如果不帶--username--email選項,將會提示你輸入這些值。

修改密碼

Django不會在user模型上存儲原始的(明文)密碼,而只是一個哈希(完整的細節(jié)參見文檔:密碼是如何管理的)。因為這個原因,不要嘗試直接操作user的password屬性。這也是為什么創(chuàng)建一個user時要使用輔助函數(shù)。

若要修改一個用戶的密碼,你有幾種選擇:

manage.py changepassword *username*提供一種從命令行修改User密碼的方法。它提示你修改一個給定user的密碼,你必須輸入兩次。如果它們匹配,新的密碼將會立即修改。如果你沒有提供user,命令行將嘗試修改與當(dāng)前系統(tǒng)用戶匹配的用戶名的密碼。

你也可以通過程序修改密碼,使用[set_password()](../../ref/contrib/auth.html#django.contrib.auth.models.User.set_password ):

>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username='john')
>>> u.set_password('new password')
>>> u.save()

如果你安裝了Django admin,你還可以在認證系統(tǒng)的admin頁面修改user的密碼。

Django還提供viewsforms用于允許user修改他們自己密碼。

New in Django 1.7.

如果啟用了[SessionAuthenticationMiddleware](../../ref/middleware.html#django.contrib.auth.middleware.SessionAuthenticationMiddleware ),修改user的密碼將會登出他們所有的會話。 詳細信息請參閱密碼修改后會話失效。

認證Users

authenticate(**credentials)[source]

認證一個給定用戶名和密碼,請使用[authenticate()](#django.contrib.auth.authenticate )。它以關(guān)鍵字參數(shù)形式接收憑證,對于默認的配置它是usernamepassword,如果密碼對于給定的用戶名有效它將返回一個[User](../../ref/contrib/auth.html#django.contrib.auth.models.User )對象。如果密碼無效,[authenticate()](#django.contrib.auth.authenticate )返回None。例子:

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    # the password verified for the user
    if user.is_active:
        print()
    else:
        print()
else:
    # the authentication system was unable to verify the username and password
    print()

這是認證一系列憑證的低級的方法;例如,它被[RemoteUserMiddleware](../../ref/middleware.html#django.contrib.auth.middleware.RemoteUserMiddleware )使用。除非你正在編寫你自己的認證系統(tǒng),你可能不會使用到它。當(dāng)然如果你在尋找一種登錄user的方法,請參見[login_required()](#django.contrib.auth.decorators.login_required )裝飾器。

權(quán)限和授權(quán)

Django從開始就帶有一個簡單的權(quán)限系統(tǒng)。它提供一種分配權(quán)限給特定的用戶和用戶組的方法。

它被Django的admin站點使用,但歡迎你在你自己的代碼中使用。

Django admin 站點使用如下的權(quán)限:

  • 查看"add"表單并添加一個只限具有該類型對象的“add”權(quán)限的用戶對象。
  • 查看修改列表、查看“change”表單以及修改一個只限具有該類型對象的“change”權(quán)限的用戶對象。
  • 刪除一個只限具有該類型對象的“delete”權(quán)限的用戶對象。

權(quán)限不但可以根據(jù)每個對象的類型,而且可以根據(jù)特定的對象實例設(shè)置。通過使用[ModelAdmin](../../ref/contrib/admin/index.html#django.contrib.admin.ModelAdmin )類提供的[has_add_permission()](../../ref/contrib/admin/index.html#django.contrib.admin.ModelAdmin.has_add_permission )、[has_change_permission()](../../ref/contrib/admin/index.html#django.contrib.admin.ModelAdmin.has_change_permission )和[has_delete_permission()](../../ref/contrib/admin/index.html#django.contrib.admin.ModelAdmin.has_delete_permission )方法,可以針對相同類型的不同對象實例自定義權(quán)限。

[User](../../ref/contrib/auth.html#django.contrib.auth.models.User )對象具有兩個多對多的字段:groupsuser_permissions。[User](../../ref/contrib/auth.html#django.contrib.auth.models.User )對象可以用和其它Django 模型一樣的方式訪問它們相關(guān)的對象:

myuser.groups = [group_list]
myuser.groups.add(group, group, ...)
myuser.groups.remove(group, group, ...)
myuser.groups.clear()
myuser.user_permissions = [permission_list]
myuser.user_permissions.add(permission, permission, ...)
myuser.user_permissions.remove(permission, permission, ...)
myuser.user_permissions.clear()

默認的權(quán)限

當(dāng)django.contrib.auth在你的INSTALLED_APPS設(shè)置中列出時,它將確保為你安裝的應(yīng)用中的每個Django模型創(chuàng)建3個默認的權(quán)限 – add、change和delete。

這些權(quán)限將在你運行manage.py migrate時創(chuàng)建;在添加django.contrib.authINSTALLED_APPS中之后,當(dāng)你第一次運行migrate時,將會為之前安裝的模型創(chuàng)建默認的權(quán)限,包括與其同時正在安裝的新的模型。之后,每當(dāng)你運行manage.py migrate時,它都將為新的模型創(chuàng)建默認的權(quán)限。

假設(shè)你有個應(yīng)用的[app_label](../../ref/models/options.html#django.db.models.Options.app_label )是foo和一個名為Bar的模型,要測試基本的權(quán)限,你應(yīng)該使用:

  • add: user.has_perm('foo.add_bar')
  • change: user.has_perm('foo.change_bar')
  • delete: user.has_perm('foo.delete_bar')

很少直接訪問[Permission](../../ref/contrib/auth.html#django.contrib.auth.models.Permission )模型。

[django.contrib.auth.models.Group](../../ref/contrib/auth.html#django.contrib.auth.models.Group )模型是用戶分類的一種通用的方式,通過這種方式你可以應(yīng)用權(quán)限或其它標(biāo)簽到這些用戶。一個用戶可以屬于任意多個組。

組中某個用戶自動具有賦給那個組的權(quán)限。例如,如果組Site editors具有權(quán)限 can_edit_home_page,那么該組中的任何用戶都具有該權(quán)限。

出權(quán)限之外,組還是給用戶分類的一種方便的方法以給他們某些標(biāo)簽或擴展的功能。例如,你可以創(chuàng)建一個組'Special users',然后你可以這樣寫代碼,給他們訪問你的站點僅限會員的部分,或者給他們發(fā)僅限于會員的郵件。

用程序創(chuàng)建權(quán)限

雖然custom permissions可以定義在Meta類中,你還可以直接創(chuàng)建權(quán)限。例如,你可以為myapp中的BlogPost 創(chuàng)建can_publish權(quán)限:

from myapp.models import BlogPost
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(codename='can_publish',
                                       name='Can Publish Posts',
                                       content_type=content_type)

然后該權(quán)限可以通過user_permissions屬性分配給一個[User](../../ref/contrib/auth.html#django.contrib.auth.models.User ),或者通過permissions屬性分配給[Group](../../ref/contrib/auth.html#django.contrib.auth.models.Group )。

權(quán)限的緩存

[ModelBackend](../../ref/contrib/auth.html#django.contrib.auth.backends.ModelBackend )在第一次需要訪問User對象來檢查權(quán)限時會緩存它們的權(quán)限。這對于請求-響應(yīng)循環(huán)還是比較好的,因為在權(quán)限添加進來之后并不會立即檢查(例如在admin中)。如果你正在添加權(quán)限并需要立即檢查它們,例如在一個測試或視圖中,最簡單的解決辦法是從數(shù)據(jù)庫中重新獲取User。 例如:

from django.contrib.auth.models import Permission, User
from django.shortcuts import get_object_or_404

def user_gains_perms(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    # any permission check will cache the current set of permissions
    user.has_perm('myapp.change_bar')

    permission = Permission.objects.get(codename='change_bar')
    user.user_permissions.add(permission)

    # Checking the cached permission set
    user.has_perm('myapp.change_bar')  # False

    # Request new instance of User
    user = get_object_or_404(User, pk=user_id)

    # Permission cache is repopulated from the database
    user.has_perm('myapp.change_bar')  # True

    ...

Web請求中的認證

Django使用會話和中間件來攔截[request 對象](../../ref/request-response.html#django.http.HttpRequest )到認證系統(tǒng)中。

它們在每個請求上提供一個[request.user](../../ref/request-response.html#django.http.HttpRequest.user )屬性,表示當(dāng)前的用戶。如果當(dāng)前的用戶沒有登入,該屬性將設(shè)置成[AnonymousUser](../../ref/contrib/auth.html#django.contrib.auth.models.AnonymousUser )的一個實例,否則它將是[User](../../ref/contrib/auth.html#django.contrib.auth.models.User )的實例。

你可以通過[is_authenticated()](../../ref/contrib/auth.html#django.contrib.auth.models.User.is_authenticated )區(qū)分它們,像這樣:

if request.user.is_authenticated():
    # Do something for authenticated users.
    ...
else:
    # Do something for anonymous users.
    ...

如何登入一個用戶

如果你有一個認證了的用戶,你想把它附帶到當(dāng)前的會話中 - 這可以通過[login()](#django.contrib.auth.login )函數(shù)完成。

login()[source]

從視圖中登入一個用戶,請使用[login()](#django.contrib.auth.login )。它接受一個[HttpRequest](../../ref/request-response.html#django.http.HttpRequest )對象和一個[User](../../ref/contrib/auth.html#django.contrib.auth.models.User )對象。[login()](#django.contrib.auth.login )使用Django的會話框架保存用戶的ID在會話中。

注意任何在匿名會話中設(shè)置的數(shù)據(jù)都會在用戶登入后的會話中都會記住。

這個例子展示你可能如何使用[authenticate()](#django.contrib.auth.authenticate )和 [login()](#django.contrib.auth.login ):

from django.contrib.auth import authenticate, login

def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)
    if user is not None:
        if user.is_active:
            login(request, user)
            # Redirect to a success page.
        else:
            # Return a 'disabled account' error message
            ...
    else:
        # Return an 'invalid login' error message.
        ...

先調(diào)用authenticate()

當(dāng)你是手工登入一個用戶時,你_必須_在調(diào)用[login()](#django.contrib.auth.login )之前通過[authenticate()](#django.contrib.auth.authenticate )成功地認證該用戶。[authenticate()](#django.contrib.auth.authenticate )在[User](../../ref/contrib/auth.html#django.contrib.auth.models.User )上設(shè)置一個屬性標(biāo)識哪種認證后臺成功認證了該用戶(細節(jié)參見后臺的文檔),且該信息在后面登錄的過程中是需要的。如果你視圖登入一個直接從數(shù)據(jù)庫中取出的用戶,將會拋出一個錯誤。

如何登出一個用戶

logout()[source]

若要登出一個已經(jīng)通過[django.contrib.auth.login()](#django.contrib.auth.login )登入的用戶,可以在你的視圖中使用[django.contrib.auth.logout()](#django.contrib.auth.logout )。 它接收一個[HttpRequest](../../ref/request-response.html#django.http.HttpRequest )對象且沒有返回值。例如:

from django.contrib.auth import logout

def logout_view(request):
    logout(request)
    # Redirect to a success page.

注意,即使用戶沒有登入[logout()](#django.contrib.auth.logout )也不會拋出任何錯誤。

當(dāng)你調(diào)用[logout()](#django.contrib.auth.logout )時,當(dāng)前請求的會話數(shù)據(jù)將被完全清除。所有存在的數(shù)據(jù)都將清除。這是為了防止另外一個人使用相同的Web瀏覽器登入并訪問前一個用戶的會話數(shù)據(jù)。如果你想在用戶登出之后>可以立即訪問放入會話中的數(shù)據(jù),請在調(diào)用[django.contrib.auth.logout()](#django.contrib.auth.logout )_之后_放入。

限制訪問給登陸后的用戶

原始的方法

限制頁面訪問的簡單、原始的方法是檢查[request.user.is_authenticated()](../../ref/contrib/auth.html#django.contrib.auth.models.User.is_authenticated )并重定向到一個登陸頁面:

from django.conf import settings
from django.shortcuts import redirect

def my_view(request):
    if not request.user.is_authenticated():
        return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
    # ...

...或者顯示一個錯誤信息:

from django.shortcuts import render

def my_view(request):
    if not request.user.is_authenticated():
        return render(request, 'myapp/login_error.html')
    # ...

login_required 裝飾器

login_required([_redirect_field_name=REDIRECT_FIELDNAME, _loginurl=None])[source]

作為一個快捷方式,你可以使用便捷的[login_required()](#django.contrib.auth.decorators.login_required )裝飾器:

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    ...

[login_required()](#django.contrib.auth.decorators.login_required )完成下面的事情:

  • 如果用戶沒有登入,則重定向到settings.LOGIN_URL,并傳遞當(dāng)前查詢字符串中的絕對路徑。例如:/accounts/login/?next=/polls/3/。
  • 如果用戶已經(jīng)登入,則正常執(zhí)行視圖。視圖的代碼可以安全地假設(shè)用戶已經(jīng)登入。

默認情況下,在成功認證后用戶應(yīng)該被重定向的路徑存儲在查詢字符串的一個叫做)帶有一個可選的redirect_field_name`參數(shù):

from django.contrib.auth.decorators import login_required

@login_required(redirect_field_name='my_redirect_field')
def my_view(request):
    ...

注意,如果你提供一個值給redirect_field_name,你非??赡芡瑫r需要自定義你的登錄模板,因為存儲重定向路徑的模板上下文變量將使用redirect_field_name值作為它的鍵,而不是默認的"next"。

[login_required()](#django.contrib.auth.decorators.login_required )還帶有一個可選的login_url參數(shù)。例如:

from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def my_view(request):
    ...

注意,如果你沒有指定login_url參數(shù),你需要確保settings.LOGIN_URL并且你的登錄視圖正確關(guān)聯(lián)。例如,使用默認值,可以添加下面幾行到你的URLconf中:

from django.contrib.auth import views as auth_views

url(r'^accounts/login/$', auth_views.login),

settings.LOGIN_URL同時還接收視圖函數(shù)名和命名的URL模式。這允許你自由地重新映射你的URLconf中的登錄視圖而不用更新設(shè)置。

login_required裝飾器不檢查user的is_active標(biāo)志位。

給已驗證登錄的用戶添加訪問限制

基于特定的權(quán)限和其他方式來限制訪問,你最好按照前面所敘述的那樣操做。

簡單的方法就是在視圖中直接運行你對[request.user](../../ref/request-response.html#django.http.HttpRequest.user )的測試。例如,視圖檢查用戶的郵件屬于特定的地址(例如@example.com),若不是,則重定向到登錄頁面。

from django.shortcuts import redirect

def my_view(request):
    if not request.user.email.endswith('@example.com'):
        return redirect('/login/?next=%s' % request.path)
    # ...

user_passes_test(func[, _loginurl=None, _redirect_field_name=REDIRECT_FIELDNAME])[source]

你可以用方便的 user_passes_test 裝飾器,當(dāng)回掉函數(shù)返回 False 時會執(zhí)行一個重定向操作:

from django.contrib.auth.decorators import user_passes_test

def email_check(user):
    return user.email.endswith('@example.com')

@user_passes_test(email_check)
def my_view(request):
    ...

[user_passes_test()](#django.contrib.auth.decorators.user_passes_test ) 要求一個以[User](../../ref/contrib/auth.html#django.contrib.auth.models.User ) 對象為參數(shù)的回掉函數(shù),若用戶允許訪問此視圖,返回 True。注意,[user_passes_test()](#django.contrib.auth.decorators.user_passes_test ) 不會自動檢查 [User](../../ref/contrib/auth.html#django.contrib.auth.models.User ) 是否是不是匿名對象。

[user_passes_test()](#django.contrib.auth.decorators.user_passes_test )接收兩個額外的參數(shù):

login_url

讓你指定那些沒有通過檢查的用戶要重定向至哪里。若不指定其值,它可能是默認的 settings.LOGIN_URL。

redirect_field_name

與[login_required()](#django.contrib.auth.decorators.login_required )的參數(shù)相同。把它設(shè)置為 None 來把它從 URL 中移除,當(dāng)你想把通不過檢查的用戶重定向到?jīng)]有next page 的非登錄頁面時。

例如:

@user_passes_test(email_check, login_url='/login/')
def my_view(request):
    ...

permission_required 裝飾器

permission_required(perm[, _loginurl=None, _raiseexception=False])[source]

檢查一個用戶是否有指定的權(quán)限是相對常見的需求。因此,Django 提供了一個快捷方式: [permission_required()](#django.contrib.auth.decorators.permission_required ) 裝飾器:

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote')
def my_view(request):
    ...

[has_perm()](../../ref/contrib/auth.html#django.contrib.auth.models.User.has_perm ) 方法, 權(quán)限名稱采用如下方法 "<app label>.<permission codename>" (例如 polls.can_vote 表示在 polls 應(yīng)用下一個模塊的權(quán)限。

要注意[permission_required()](#django.contrib.auth.decorators.permission_required ) 也接受一個可選的login_url參數(shù)。例如:

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote', login_url='/loginpage/')
def my_view(request):
    ...

在 [login_required()](#django.contrib.auth.decorators.login_required ) 裝飾器中, login_url默認為settings.LOGIN_URL。

如果提供了 raise_exception 參數(shù),裝飾器拋出[PermissionDenied](../../ref/exceptions.html#django.core.exceptions.PermissionDenied )異常,使用 the 403 (HTTP Forbidden) 視圖而不是重定向到登錄頁面。

Changed in Django 1.7:

[permission_required()](#django.contrib.auth.decorators.permission_required )裝飾器既可以接收一個權(quán)限序列也可以接收一個單個的權(quán)限。

對普通的視圖使用權(quán)限

若要對一個基于類的普通視圖使用權(quán)限,可以在該類上裝飾[View.dispatch](../../ref/class-based-views/base.html#django.views.generic.base.View.dispatch )方法。詳細細節(jié)參見Decorating the class。 另外一個方法是_編寫一個封裝asview()的mixin。

密碼更改后的會話失效

New in Django 1.7.

警告

這種保護只在MIDDLEWARE_CLASSES中[SessionAuthenticationMiddleware](../../ref/middleware.html#django.contrib.auth.middleware.SessionAuthenticationMiddleware )開啟的情況下應(yīng)用。如果settings.py由Django ≥ 1.7. 的startproject生成,它會被包含進來。

在Django 2.0中,會話驗證會變成強制性的, 無論是否開啟了SessionAuthenticationMiddleware 。 如果你擁有一個1.7之前的項目,或者使用不包含SessionAuthenticationMiddleware的模板生成的項目,考慮在閱讀下面的升級說明之后開啟它。

如果你的AUTH_USER_MODEL繼承自[AbstractBaseUser](customizing.html#django.contrib.auth.models.AbstractBaseUser ),或者實現(xiàn)了它自己的[get_session_auth_hash()](customizing.html#django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash )方法,驗證后的會話會包含這個函數(shù)返回的哈希值。在AbstractBaseUser的情況中,這是密碼字段的HMAC。如果開啟了SessionAuthenticationMiddleware ,Django會驗證每個請求帶有的哈希值是否匹配服務(wù)端計算出來的哈希值。這允許用戶通過修改密碼來登出所有的會話。

Django中包含的默認的密碼修改視圖,以及django.contrib.auth中的 [django.contrib.auth.views.password_change()](#django.contrib.auth.views.password_change )和user_change_password視圖 ,會使用新的密碼哈希值升級會話,以便用戶在修改密碼是不會登出。如果你擁有自定義的密碼修改視圖,并且希望具有相似的行為,使用這個函數(shù):

update_session_auth_hash(request, user)

這個函數(shù)接受當(dāng)前請求,并且會在會話哈希值得到的地方升級用戶對象,也會適當(dāng)?shù)厣墪捁V怠J褂檬纠?/p>

from django.contrib.auth import update_session_auth_hash

def password_change(request):
    if request.method == 'POST':
        form = PasswordChangeForm(user=request.user, data=request.POST)
        if form.is_valid():
            form.save()
            update_session_auth_hash(request, form.user)
    else:
        ...

如果你在升級一個現(xiàn)存的站點,并且希望開啟這一中間件,而不希望你的所有用戶之后重新登錄,你可以首先升級到DJango1.7并且運行它一段時間,以便所有會話在用戶登錄時自然被創(chuàng)建,它們包含上面描述的會話哈希。一旦你使用[SessionAuthenticationMiddleware](../../ref/middleware.html#django.contrib.auth.middleware.SessionAuthenticationMiddleware )開始運行你的站點,任何沒有登錄并且會話使用驗證哈希值升級過的用戶的現(xiàn)有會話都會失效,并且需要重新登錄。

注意

雖然[get_session_auth_hash()](customizing.html#django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash )給予SECRET_KEY,使用新的私鑰升級你的站點會使所有現(xiàn)有會話失效。

認證的視圖

Django提供一些視圖,你可以用來處理登錄、登出和密碼管理。它們使用stock auth 表單,但你也可以傳遞你自己的表單。

Django沒有為認證視圖提供默認的模板。你應(yīng)該為你想要使用的視圖創(chuàng)建自己的模板。模板的上下文定義在每個視圖中,參見所有的認證視圖.

使用視圖

有幾種不同的方法在你的項目中使用這些視圖。最簡單的方法是包含django.contrib.auth.urls中提供的URLconf到你自己的URLconf中,例如

urlpatterns = [
    url('^', include('django.contrib.auth.urls'))
]

這將包含進下面的URL模式:

^login/$ [name='login']
^logout/$ [name='logout']
^password_change/$ [name='password_change']
^password_change/done/$ [name='password_change_done']
^password_reset/$ [name='password_reset']
^password_reset/done/$ [name='password_reset_done']
^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$ [name='password_reset_confirm']
^reset/done/$ [name='password_reset_complete']

這些視圖提供了一個簡單易記的URL名稱。使用命名URL模式的細節(jié)請參見URL文檔。

如果你想更多地控制你的URL,你可以在你的URLconf中引用一個特定的視圖:

urlpatterns = [
    url('^change-password/', 'django.contrib.auth.views.password_change')
]

這些視圖具有可選的參數(shù),你可以用來改變視圖的行為。例如,如果你想修改一個視圖使用的模板名稱,你可以提供template_name參數(shù)。實現(xiàn)它的一種方法是在URLconf中提供一個關(guān)鍵字參數(shù),它們將被傳遞到視圖中。例如:

urlpatterns = [
    url(
        '^change-password/',
        'django.contrib.auth.views.password_change',
        {'template_name': 'change-password.html'}
    )
]

所有的視圖都返回一個[TemplateResponse](../../ref/template-response.html#django.template.response.TemplateResponse ) 實例,這允許你在渲染之前很容易自定義響應(yīng)。實現(xiàn)它的一種方法是在你自己的視圖中包裝一個視圖:

from django.contrib.auth import views

def change_password(request):
    template_response = views.password_change(request)
    # Do something with `template_response`
    return template_response

更多的細節(jié),參見TemplateResponse文檔。

所有的認證視圖

下面列出了django.contrib.auth提供的所有視圖。實現(xiàn)細節(jié)參見使用視圖。

login(request[, _templatename, _redirect_fieldname, _authenticationform, _currentapp, _extracontext])[source]

URL 名稱:login

關(guān)于使用命名URL模式的細節(jié)參見URL 文檔

可選的參數(shù):

  • template_name: 用于用戶登錄視圖的模板名。默認為registration/login.html。
  • redirect_field_name: GET字段的名稱,包含登陸后重定向URL。默認為next。
  • authentication_form: 用于認證的可調(diào)用對象(通常只是一個表單類)。默認為[AuthenticationForm](#django.contrib.auth.forms.AuthenticationForm )。
  • current_app: 指示包含當(dāng)前視圖的是哪個應(yīng)用。更多信息參見命名URL的解析策略
  • extra_context: 一個上下文數(shù)據(jù)的字典,將被添加到傳遞給模板的默認上下文數(shù)據(jù)中。

下面是django.contrib.auth.views.login所做的事情:

  • 如果通過 GET調(diào)用,它顯示一個POST給相同URL的登錄表單。后面有更多這方面的信息。
  • 如果通過POST調(diào)用并帶有用戶提交的憑證,它會嘗試登入該用戶。如果登入成功,該視圖重定向到next中指定的URL。如果next沒有提供,它重定向到settings.LOGIN_REDIRECT_URL(默認為/accounts/profile/)。如果登入不成功,則重新顯示登錄表單。

你需要提供html模板給login,默認調(diào)用registration/login.html。模板會得到4個模板上下文變量:

  • form: 一個表示[AuthenticationForm](#django.contrib.auth.forms.AuthenticationForm )的[Form](../../ref/forms/api.html#django.forms.Form )對象。
  • next: 登入成功之后重定向的URL。它還可能包含一個查詢字符串。
  • site: 如果你沒有安裝site框架,這將被設(shè)置成[RequestSite](../../ref/contrib/sites.html#django.contrib.sites.requests.RequestSite )的一個實例,它從當(dāng)前的[HttpRequest](../../ref/request-response.html#django.http.HttpRequest )獲得site名稱和域名。
  • site_name: site.name的別名。如果你沒有安裝site框架,這將被設(shè)置成[request.META['SERVERNAME']](../../ref/request-response.html#django.http.HttpRequest.META )的值。關(guān)于site 的更多信息,參見[“sites” 框架_](../../ref/contrib/sites.html)。

如果你不喜歡調(diào)用registration/login.html,你可以通過額外的參數(shù)傳遞template_name參數(shù)給你URLconf中的視圖。例如,下面URLconf中的行將使用myapp/login.html

url(r'^accounts/login/$', auth_views.login, {'template_name': 'myapp/login.html'}),

通過傳遞redirect_field_name給視圖,你還可以指定GET字段的值,它包含登入成功后的重定向的URL。默認情況下,該字段叫做next。

下面是一個registration/login.html模板的示例,你可以用它來作為起點。它假設(shè)你有一個定義了content塊的base.html模板:

{% extends "base.html" %}

{% block content %}

{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}

<form method="post" action="{% url 'django.contrib.auth.views.login' %}">
{% csrf_token %}
<table>
<tr>
    <td>{{ form.username.label_tag }}</td>
    <td>{{ form.username }}</td>
</tr>
<tr>
    <td>{{ form.password.label_tag }}</td>
    <td>{{ form.password }}</td>
</tr>
</table>

<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>

{% endblock %}

如果你自定義認證(參見Customizing Authentication),你可以通過authentication_form參數(shù)傳遞一個自定義的認證表單給登錄視圖。該表單必須在它的__init__方法中接收一個request關(guān)鍵字參數(shù),并提供一個get_user方法,此方法返回認證過的用戶對象(這個方法永遠只在表單驗證成功后調(diào)用)。

logout(request[, _nextpage, _templatename, _redirect_fieldname, _currentapp, _extracontext])[source]

登出一個用戶。

URL名稱:logout

可選的參數(shù):

  • next_page: 登出之后要重定向的URL。
  • template_name: 用戶登出之后,要展示的模板的完整名稱。如果不提供任何參數(shù),默認為registration/logged_out.html
  • redirect_field_name: 包含登出之后所重定向的URL的GET字段的名稱。默認為 next。如果提供了GET參數(shù),會覆蓋next_page URL。
  • current_app: 一個提示,表明哪個應(yīng)用含有了當(dāng)前視圖。 詳見 命名空間下的URL解析策略 。
  • extra_context: 一個上下文數(shù)據(jù)的字典,會被添加到向模板傳遞的默認的上下文數(shù)據(jù)中。

模板上下文:

  • title: 本地化的字符串“登出”。
  • site: 根據(jù)SITE_ID 設(shè)置的當(dāng)前[站點](../../ref/contrib/sites.html#django.contrib.sites.models.Site )。如果你并沒有安裝站點框架,會設(shè)置為 [RequestSite](../../ref/contrib/sites.html#django.contrib.sites.requests.RequestSite )的示例,它從當(dāng)前[HttpRequest](../../ref/request-response.html#django.http.HttpRequest )來獲取站點名稱和域名。
  • site_name: site.name的別名。如果沒有安裝站點框架,會設(shè)置為[request.META['SERVERNAME']](../../ref/request-response.html#django.http.HttpRequest.META )。站點的更多信息請見[“站點”框架_](../../ref/contrib/sites.html)。
  • current_app: 一個提示,表明哪個應(yīng)用含有了當(dāng)前視圖。 詳見 命名空間下的URL解析策略 。
  • extra_context: 一個上下文數(shù)據(jù)的字典,會被添加到向模板傳遞的默認的上下文數(shù)據(jù)中。

logout_then_login(request[, _loginurl, _currentapp, _extracontext])[source]

登出一個用戶,然后重定向到登錄頁面。

URL 名稱: 沒有提供默認的URL

可選的參數(shù):

  • login_url: 登錄頁面要重定向的URL。如果沒有提供,默認為settings.LOGIN_URL。
  • current_app: 一個提示,表明哪個應(yīng)用含有了當(dāng)前視圖。詳見 命名空間下的URL解析策略 。
  • extra_context: 一個上下文數(shù)據(jù)的字典,會被添加到向模板傳遞的默認的上下文數(shù)據(jù)中。

password_change(request[, _templatename, _post_changeredirect, _password_changeform, _currentapp, _extracontext])[source]

允許一個用戶修改他的密碼。

URL 名稱:password_change

可選的參數(shù):

  • template_name: 用來顯示修改密碼表單的template的全名。如果沒有提供,默認為registration/password_change_form.html 。
  • post_change_redirect: 密碼修改成功后重定向的URL。
  • password_change_form: 一個自定義的“修改密碼”表單,必須接受user 關(guān)鍵詞參數(shù)。表單用于實際修改用戶密碼。默認為 [PasswordChangeForm](#django.contrib.auth.forms.PasswordChangeForm )。
  • current_app: 一個提示,暗示哪個應(yīng)用包含當(dāng)前的視圖。詳見 命名空間下的URL解析策略 。
  • extra_context: 上下文數(shù)據(jù)的字典,會添加到傳遞給模板的默認的上下文數(shù)據(jù)中。

模板上下文:

  • form: 密碼修改表單(請見上面的password_change_form)。

password_change_done(request[, _templatename, _currentapp, _extracontext])[source]

這個頁面在用戶修改密碼之后顯示。

URL 名稱:password_change_done

可選參數(shù):

  • template_name: 所使用模板的完整名稱。如果沒有提供,默認為registration/password_change_done.html。
  • current_app: 一個提示,暗示哪個應(yīng)用包含當(dāng)前的視圖。 詳見 命名空間下的URL解析策略
  • extra_context: 上下文數(shù)據(jù)的字典,會添加到傳遞給模板的默認的上下文數(shù)據(jù)中。

passwor