Django認證系統

前言

Django的簡單認證系統,後期會分享一些對象級別的權限校驗。

Django認證系統

使用Django認證系統

這篇文檔解釋默認配置下Django認證系統的使用。這些配置已經逐步可以滿足大部分常見項目的需要,可以處理範圍非常廣泛的任務,且具有一套細緻的密碼和權限實現。對於需要與默認配置不同需求的項目,Django支持擴展和自定義認證。

Django的認證同時提供認證和授權,並通常統一稱為認證系統,因為這些功能某些地方是耦合的。

User對象

User對象是認證系統的核心。它們通常表示與你的站點進行交互的用戶,並用於啟用限制訪問、註冊用戶信息和給創建者關聯內容等。在Django的認證框架中只存在一種類型的用戶,因此諸如‘superusers‘或管理員‘staff‘用戶只是具有特殊屬性集的user對象,而不是不同類型的user對象。

默認user的基本屬性有:

  • 用戶名
  • 密碼
  • 電子郵件
  • 名字

完整的參考請參閱完整的API文檔,以下的內容更偏重特定的任務。

創建user

創建users最直接的方法是使用create_user()輔助函數:

<code> > from django.contrib.auth.models import User 
 > user = User.objects.create_user(‘laowang‘, ‘[email protected]‘, ‘laowangpassword‘) 
 
 
 
 > user.last_name = ‘Lio‘ 
 > user.save()/<code>

如果你已經安裝了Django admin,你也可以交互式地創建users.

創建superusers

使用createsuperuser命令創建superusers:

<code>$ python manage.py createsuperuser --username=laowang [email protected]/<code>

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

修改密碼

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

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

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

你也可以通過程序修改密碼,使用set_password():

<code> > from django.contrib.auth.models import User 
 > u = User.objects.get(username=‘laowang‘) 
 > u.set_password(‘new password‘) 
 > u.save()/<code>

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

Django還提供views和forms用於允許user修改他們自己密碼。

New in Django 1.7.

如果啟用了SessionAuthenticationMiddleware,修改user的密碼將會登出他們所有的會話。 詳細信息請參閱密碼修改後會話失效。

認證Users

authenticate(**credentials)[source]?

請使用authenticate(),認證一組給定的用戶名和密碼。它接收關鍵字參數形式的憑證,使用默認配置時參數是username和password,如果密碼能夠匹配給定的用戶名,它將返回一個User對象。如果密碼無效,authenticate()返回None。例子:

<code>

from

django.contrib.auth

import

authenticate user = authenticate(username=‘laowang‘, password=‘secret‘)

if

user

is

not

None

:

if

user.is_active: print(

"User is valid, active and authenticated"

)

else

: print(

"The password is valid, but the account has been disabled!"

)

else

: print(

"The username and password were incorrect."

)/<code>

注意:

這是認證一系列憑證的低級的方法;例如,它被RemoteUserMiddleware使用。除非你正在編寫你自己的認證系統,否則你可能不會使用到它。當然如果你在尋找一種登錄user的方法,請參見login_required()裝飾器。

權限和授權

Django本身提供了一個簡單的權限系統。它提供一種分配權限給特定的用戶和用戶組的方法。

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

Django admin 站點使用如下的權限:

  • 擁有該類型對象"add"權限的用戶才可以訪問"add"表單以及添加一個該類型對象。
  • 查看修改列表、查看“change”表單以及修改一個對象的權利只限於具有該類型對象的“change”權限的用戶擁有。
  • 用戶必須在一個對象上具有“delete”權限,才能刪除這個對象。

權限不但可以根據每個對象的類型,而且可以根據特定的對象實例設置。通過使用ModelAdmin類提供的has_add_permission()、has_change_permission()和has_delete_permission()方法,可以針對相同類型的不同對象實例自定義權限。

User對象具有兩個多對多的字段:groups和user_permissions。User對象可以用和其它Django 模型一樣的方式訪問它們相關的對象:

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

默認的權限?

當django.contrib.auth在你的INSTALLED_APPS設置中列出時,它將確保為你安裝的應用中的每個Django模型創建3個默認的權限 – add、change和delete。

這些權限將在你運行manage.py migrate時創建;在添加django.contrib.auth到INSTALLED_APPS中之後,當你第一次運行migrate時,將會為之前安裝的模型創建默認的權限,包括與此同時正在安裝的新的模型。之後,每當你運行manage.py migrate時,它都將為新的模型創建默認的權限。

假設你有個app_label叫做foo的應用,這個應用有一個名為Bar的模型,要測試基本的權限,你應該使用:

<code>

add

user

.has_perm

(‘

foo

.add_bar

‘)

change

user

.has_perm

(‘

foo

.change_bar

‘)

delete

user

.has_perm

(‘

foo

.delete_bar

‘)/<code>

很少直接訪問Permission模型。

django.contrib.auth.models.Group模型是用戶分類的一種通用的方式,通過這種方式你可以應用權限或其它標籤到這些用戶。一個用戶可以屬於任意多個組。

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

除權限之外,組還是給用戶分類的一種方便的方法以給他們某些標籤或擴展的功能。例如,你可以創建一個組‘Special users‘,然後你可以這樣寫代碼,給他們訪問你的站點僅限會員的部分,或者給他們發僅限於會員的郵件。

用程序創建權限

雖然自定義的權限可以定義在模型的Meta類中,你還可以直接創建權限。例如,你可以為myapp中的BlogPost 創建can_publish權限:

<code>

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)

/<code>

然後該權限可以通過user_permissions屬性分配給一個User,或者通過permissions屬性分配給Group。

權限的緩存

ModelBackend在第一次需要訪問User對象來檢查權限時會緩存它們的權限。這對於請求-響應循環還是比較好的,因為在權限添加進來之後並不會立即檢查(例如在admin中)。如果你正在添加權限並需要立即檢查它們,例如在一個測試或視圖中,最簡單的解決辦法是從數據庫中重新獲取User。 例如:

<code>

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) user.has_perm(‘myapp.change_bar‘) permission = Permission.objects.get(codename=‘change_bar‘) user.user_permissions.add(permission) user.has_perm(‘myapp.change_bar‘) user = get_object_or_404(User, pk=user_id) user.has_perm(‘myapp.change_bar‘) /<code>

Web請求中的認證

Django使用會話和中間件來攔截request 對象到認證系統中。

它們在每個請求上提供一個request.user屬性,表示當前的用戶。如果當前的用戶沒有登入,該屬性將設置成AnonymousUser的一個實例,否則它將是User的實例。

你可以通過is_authenticated()區分它們,像這樣:

<code>

if

request.user.is_authenticated():

else

:

/<code>

如何登入一個用戶

如果你有一個認證了的用戶,你想把它附帶到當前的會話中 - 這可以通過login()函數完成。

login()[source]?

從視圖中登入一個用戶,請使用login()。它接受一個HttpRequest對象和一個User對象。login()使用Django的session框架來將用戶的ID保存在session中。

注意任何在匿名會話中設置的數據都會在用戶登入後的會話中都會記住。

下面的示例向你演示如何使用authenticate() 和login():

<code>

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:

user)

else

:

...

else

:

...

/<code>

先調用authenticate():

當你是手工登入一個用戶時,你必須在調用login()之前通過authenticate()成功地認證該用戶。authenticate()在用戶上設置一個屬性,注意哪個認證後端成功驗證了該用戶(有關詳細信息,請參閱後端文檔),以及此信息以後在登錄過程中需要。如果你試圖登入一個直接從數據庫中取出的用戶,將會拋出一個錯誤。

如何登出一個用戶

logout()[source]?

若要登出一個已經通過django.contrib.auth.login()登入的用戶,可以在你的視圖中使用django.contrib.auth.logout()。 它接收一個HttpRequest對象且沒有返回值。例如:

<code>

from

django.contrib.auth

import

logout

def

logout_view

(request)

:

logout(request) /<code>

注意,即使用戶沒有登入,logout()也不會拋出任何錯誤。

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

只允許登錄的用戶訪問

原始的方法

限制頁面訪問的簡單、原始的方法是檢查request.user.is_authenticated()並重定向到一個登陸頁面:

<code>

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)) /<code>

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

<code>

from

django.shortcuts

import

render

def

my_view

(request)

:

if

not

request.user.is_authenticated():

return

render(request, ‘myapp/login_error.html‘) /<code>

login_required 裝飾器

login_required([redirect_field_name=REDIRECT_FIELD_NAME, login_url=None])[source]?

作為一個快捷方式,你可以使用便捷的login_required()裝飾器:

<code>

from

django.contrib.auth.decorators

import

login_required

def

my_view

(request)

:

.../<code>

login_required()完成下面的事情:

  • 如果用戶沒有登入,則重定向到settings.LOGIN_URL,並將當前訪問的絕對路徑傳遞到查詢字符串中。例如:/accounts/login/?next=/polls/3/。
  • 如果用戶已經登入,則正常執行視圖。視圖的代碼可以安全地假設用戶已經登入。

默認情況下,在成功認證後用戶應該被重定向的路徑存儲在查詢字符串的一個叫做"next"的參數中。如果對該參數你傾向使用一個不同的名字,login_required()帶有一個可選的redirect_field_name參數:

<code>

from

django.contrib.auth.decorators

import

login_required

def

my_view

(request)

:

.../<code>

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

login_required()還帶有一個可選的login_url參數。例如:

<code>

from

django.contrib.auth.decorators

import

login_required

def

my_view

(request)

:

.../<code>

注意,如果你沒有指定login_url參數,你需要確保settings.LOGIN_URL與你的登錄視圖正確關聯。例如,使用默認值,可以添加下面幾行到你的URLconf中:

<code>

from

django.contrib.auth

import

views

as

auth_views url(r‘^accounts

/login/

$‘, auth_views.login),/<code>

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

login_required裝飾器不檢查user的is_active標誌位。

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

基於特定的權限和其他方式來限制訪問,你最好按照前面描述的那樣操作。

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

<code>

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[, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME])

[source]

?/<code>

你可以用方便的 user_passes_test 裝飾器,當回調函數返回 False 時會執行一個重定向操作:

<code>

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): .../<code>

user_passes_test() 要求一個以User 對象為參數的回調函數,若用戶允許訪問此視圖,返回 True。注意,user_passes_test() 不會自動檢查 User 是否為匿名對象。

user_passes_test()接收兩個額外的參數:

login_url

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

redirect_field_name

與login_required()的參數相同。把它設置為 None 來把它從 URL 中移除,當你想把通不過檢查的用戶重定向到沒有next page 的非登錄頁面時。

例如:

<code>@user_passes_test(email_check, login_url=‘/login/‘) 

def

my_view

(request)

: .../<code>

permission_required 裝飾器

permission_required(perm[, login_url=None, raise_exception=False])[source]?

檢查一個用戶是否有指定的權限是相對常見的需求。因此,Django 提供了一個快捷方式: permission_required() 裝飾器:

<code>

from

django.contrib.auth.decorators

import

permission_required

def

my_view

(request)

:

.../<code>

has_perm() 方法, 權限名稱採用如下方法 "." (例如 polls.can_vote表示在 polls 應用下一個模塊的權限。

要注意permission_required() 也接受一個可選的login_url參數。例如:

<code>

from

django.contrib.auth.decorators

import

permission_required

def

my_view

(request)

:

.../<code>

在 login_required() 裝飾器中, login_url默認為settings.LOGIN_URL。

如果提供了 raise_exception 參數,裝飾器拋出PermissionDenied異常,使用 the 403 (HTTP Forbidden) 視圖而不是重定向到登錄頁面。

Changed in Django 1.7:

permission_required()裝飾器既可以接收一個權限序列也可以接收一個單個的權限。

對普通的視圖使用權限?

若要對一個基於類的普通視圖使用權限,可以在該類上裝飾View.dispatch方法。詳細細節參見Decorating the class。 另外一個方法是編寫一個封裝as_view()的mixin。

密碼更改後的會話失效

New in Django 1.7.

警告

這種保護只在MIDDLEWARE_CLASSES中SessionAuthenticationMiddleware開啟的情況下應用。如果settings.py由Django ≥ 1.7. 的startproject生成,它會被包含進來。

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

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

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

<code>

update_session_auth_hash

(request, user)/<code>

這個函數接受當前請求,並且會在會話哈希值得到的地方升級用戶對象,也會適當地升級會話哈希值。使用示例:

<code>

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

form.user)

else

:

...

/<code>

如果你在升級一個現存的站點,並且希望開啟這一中間件,而不希望你的所有用戶之後重新登錄,你可以首先升級到DJango1.7並且運行它一段時間,以便所有會話在用戶登錄時自然被創建,它們包含上面描述的會話哈希。一旦你使用SessionAuthenticationMiddleware開始運行你的站點,任何沒有登錄並且會話使用驗證哈希值升級過的用戶的現有會話都會失效,並且需要重新登錄。

注意

雖然get_session_auth_hash()基於SECRET_KEY,使用新的私鑰升級你的站點會使所有現有會話失效。

認證的視圖

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

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

使用視圖

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

<code>

urlpatterns

= [ url(‘^‘, include(‘django.contrib.auth.urls‘)) ]/<code>

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

<code>^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

[

0

-

9

A-Za-z

_

\-]+)/(

?P

[

0

-

9

A-Za-z]{

1

,

13

}-[

0

-

9

A-Za-z]{

1

,

20

})/$ [name=‘password_reset_confirm‘] ^reset/done/$ [name=‘password_reset_complete‘]/<code>

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

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

<code>

urlpatterns

= [ url(‘^change-password/‘, ‘django.contrib.auth.views.password_change‘) ]/<code>

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

<code>urlpatterns = [
    url(
        ‘^

change

-

password

/‘, ‘django.contrib.auth.views.password_change‘, {‘template_name‘: ‘

change

-password.html‘} ) ]/<code>

所有的視圖都返回一個TemplateResponse 實例,這讓你在渲染前自定義響應很容易。一種方法是在你自己的視圖中封裝一個視圖:

<code>

from

django.contrib.auth

import

views

def

change_password

(request)

:

template_response = views.password_change(request)

return

template_response/<code>

更多的細節,參見TemplateResponse文檔。

所有的認證視圖

下面列出了django.contrib.auth提供的所有視圖。實現細節參見使用視圖。

login(request[, template_name, redirect_field_name, authentication_form, current_app, extra_context])[source]?

URL 名稱: login

關於使用命名URL模式的細節參見URL 文檔。

可選的參數:

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

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

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

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

  • form: 一個表示AuthenticationForm的Form對象。
  • next: 登入成功之後重定向的URL。它還可能包含一個查詢字符串。
  • site: 如果你沒有安裝site框架,這將被設置成RequestSite的一個實例,它從當前的HttpRequest獲得site名稱和域名。
  • site_name: site.name的別名。如果你沒有安裝site框架,這將被設置成request.META[‘SERVER_NAME‘]的值。關於site 的更多信息,參見“sites” 框架。

如果你不喜歡調用registration/login.html,你可以通過額外的參數傳遞template_name參數給你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模板的示例,你可以用它來作為起點。它假設你有一個定義了content塊的base.html模板:

<code>{% 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 %}/<code>

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

logout(request[, next_page, template_name, redirect_field_name, current_app, extra_context])[source]?

登出一個用戶。

URL名稱: logout

可選的參數:

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

模板上下文:

  • title: 本地化的字符串“登出”。
  • site: 根據SITE_ID 設置的當前站點。如果你並沒有安裝站點框架,會設置為 RequestSite的示例,它從當前HttpRequest來獲取站點名稱和域名。
  • site_name: site.name的別名。如果沒有安裝站點框架,會設置為request.META[‘SERVER_NAME‘]。站點的更多信息請見“站點”框架。
  • current_app: 一個提示,表明哪個應用含有了當前視圖。 詳見 命名空間下的URL解析策略 。
  • extra_context: 一個上下文數據的字典,會被添加到向模板傳遞的默認的上下文數據中。

logout_then_login(request[, login_url, current_app, extra_context])[source]?

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

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

可選的參數:

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

password_change(request[, template_name, post_change_redirect, password_change_form, current_app, extra_context])[source]?

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

URL 名稱: password_change

可選的參數:

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

模板上下文:

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

password_change_done(request[, template_name, current_app, extra_context])[source]?

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

URL 名稱: password_change_done

可選參數:

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

password_reset(request[, is_admin_site, template_name, email_template_name, password_reset_form, token_generator, post_reset_redirect, from_email, current_app, extra_context, html_email_template_name])[source]?

允許用戶通過生成一次性的連接併發送到用戶註冊的郵箱地址中來重置密碼。

如果提供的郵箱地址不在系統中存在,這個視圖不會發送任何郵件,但是用戶也不會收到任何錯誤信息。這會阻止數據洩露給潛在的攻擊者。如果你打算在這種情況提供錯誤信息,你可以繼承PasswordResetForm,並使用password_reset_form 參數。

用無效密碼標記的用戶(參見set_unusable_password())不允許請求重置密碼,為了防止使用類似於LDAP的外部驗證資源時的濫用。注意它們不會收到任何錯誤信息,因為這會暴露它們的賬戶,也不會發送任何郵件。

URL 名稱: password_reset

可選參數:

  • template_name: 用於顯示密碼重置表單的模板的完整名稱。如果不提供,則默認為registration/password_reset_form.html。
  • email_template_name: 生成帶有重置密碼鏈接的電子郵件的模板的完整名稱。如果不提供,則默認為registration/password_reset_email.html。
  • subject_template_name: 帶有重置密碼鏈接的電子郵件的標題模板的完整名稱。如果不提供,則默認為registration/password_reset_subject.txt。
  • password_reset_form: 將用於獲取要重置密碼的用戶的電子郵件的表單。默認為PasswordResetForm。
  • token_generator: 用於檢查一次性鏈接的類的實例。默認為default_token_generator,它是 django.contrib.auth.tokens.PasswordResetTokenGenerator 的一個實例。
  • post_reset_redirect: 密碼重置請求成功後,將重定向到的URL。
  • from_email: 一個有效的電子郵件地址。默認情況下Django 使用DEFAULT_FROM_EMAIL。
  • current_app: 指示哪個應用程序包含當前視圖的提示。有關詳細信息,請參閱namespaced URL resolution strategy。
  • extra_context: 將添加到傳遞給模板的默認上下文數據的上下文數據字典。
  • html_email_template_name: 用於使用密碼重置鏈接生成text/html多部分電子郵件的模板的全名。默認情況下,不發送HTML電子郵件。

New in Django 1.7:

添加了html_email_template_name。

自1.8版起已棄用:is_admin_site參數已被廢棄,將在Django2.0中被移除。

模板上下文:

  • form: 用於重置用戶密碼的表單(請參閱上面的password_reset_form)。

Email模板上下文:

  • email: user.email的別名
  • user: 根據email表單字段顯示當前User。只有有效用戶才能重置其密碼(User.is_active 是 True)。
  • site_name: site.name的別名。如果您沒有安裝網站框架,則會將其設置為request.META[‘SERVER_NAME‘]的值。有關網站的詳情,請參閱The “sites” framework。
  • domain: site.domain的別名。如果您沒有安裝網站框架,則會將其設置為request.get_host()的值。
  • protocol: http或https
  • uid: 用戶的主鍵編碼在base 64中。
  • token: 令牌檢查重置鏈接是否有效。

registration/password_reset_email.html樣例(郵件正文模板):

Someone asked for password reset for email {{ email }}. Follow the link below: {{ protocol}}://{{ domain }}{% url ‘password_reset_confirm‘ uidb64=uid token=token %}

主題模板使用了同樣的模板上下文。主題必須是單行的純文本字符串。

password_reset_done(request[, template_name, current_app, extra_context])[source]?

這個頁面在向用戶發送重置密碼的郵件後展示。如果password_reset()視圖沒有顯式設置 post_reset_redirectURL,默認會調用這個視圖。

URL名稱: password_reset_done

注意

如果提供的email地址在系統中不存在,用戶未激活,或者密碼不可用,用戶仍然會重定向到這個視圖,但是不會發送郵件。

可選參數:

  • template_name: 所使用模板的全名如果未提供,默認為registration/password_reset_done.html。
  • current_app: 指示哪個應用程序包含當前視圖的提示。有關詳細信息,請參閱命名空間網址解析策略。
  • extra_context: 將添加到傳遞給模板的默認上下文數據的上下文數據字典。

password_reset_confirm(request[, uidb64, token, template_name, token_generator, set_password_form, post_reset_redirect, current_app, extra_context])[source]?

為輸入新密碼展示表單。

URL名稱: password_reset_confirm

可選參數:

  • uidb64: 用戶的id以base 64編碼。默認值為 None.
  • token: 令牌檢查密碼是否有效。默認為None。
  • template_name: 顯示確認密碼視圖的模板的全名。默認值為registration/password_reset_confirm.html。
  • token_generator: 實例的類檢查密碼。這將默認為default_token_generator,它是django.contrib.auth.tokens.PasswordResetTokenGenerator的一個實例。
  • set_password_form: 將用於設置密碼的表單。默認為SetPasswordForm
  • post_reset_redirect: 重置密碼後重定向的網址。默認為None。
  • current_app: 指示哪個應用程序包含當前視圖的提示。有關詳細信息,請參閱命名空間網址解析策略。
  • extra_context: 將添加到傳遞給模板的默認上下文數據的上下文數據字典。

模板上下文:

  • form: 用於設置新用戶密碼的格式(參見上面的set_password_form)。
  • validlink: Boolean,如果鏈接(uidb64和token的組合)有效或未使用,則為True。

password_reset_complete(request[, template_name, current_app, extra_context])[source]?

展示一個視圖,它通知用戶密碼修改成功。

URL名稱: password_reset_complete

可選參數:

  • template_name: 顯示視圖的模板的全名。默認為registration/password_reset_complete.html。
  • current_app: 指示哪個應用程序包含當前視圖的提示。有關詳細信息,請參閱命名空間網址解析策略。
  • extra_context: 將添加到傳遞給模板的默認上下文數據的上下文數據字典。

輔助函數

redirect_to_login(next[, login_url, redirect_field_name])[source]?

重定向到登錄頁面,然後在登入成功後回到另一個URL。

必需的參數:

  • next: 登陸成功後重定向的URL

可選的參數:

  • login_url: 要重定向到的登錄頁面的URL。如果未提供,默認為settings.LOGIN_URL。
  • redirect_field_name: 包含要在註銷後重定向的URL的GET字段的名稱。如果傳遞給定的GET參數,則覆蓋next。

內建的表單

如果你不想用內建的視圖,但是又不想編寫針對該功能的表單,認證系統提供了幾個內建的表單,位於django.contrib.auth.forms:

內建的驗證表單對它們處理的用戶模型做了特定假設。如果你使用了自定義的用戶模型,可能需要為驗證系統定義你自己的表單。更多信息請見內建驗證表單與自定義用戶模型的使用的文檔。

class AdminPasswordChangeForm[source]?

Admin 站點中使用的表單,用於修改用戶密碼。

接受user作為第一個參數。

class AuthenticationForm[source]?

用於用戶登錄的表單。

接受request 作為第一個參數,它將保存在表單實例中以在子類中使用。

confirm_login_allowed(user)[source]?

New in Django 1.7.

默認情況下,AuthenticationForm 將拒絕is_active 標誌為False 的用戶。你可以自定義這個行為來決定哪些用戶可以登錄。方法是使用一個自定義的表單,它子類化AuthenticationForm 並覆蓋confirm_login_allowed 方法。如果給出的用戶不能登錄,這個方法應該引發一個ValidationError。

例如,若要允許所有用戶登錄而不管“is_active”狀態如何:

from django.contrib.auth.forms import AuthenticationForm class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm): def confirm_login_allowed(self, user): pass

或者只允許某些激活的用戶登錄:

class PickyAuthenticationForm(AuthenticationForm): def confirm_login_allowed(self, user): if not user.is_active: raise forms.ValidationError( _("This account is inactive."), code=‘inactive‘, ) if user.username.startswith(‘b‘): raise forms.ValidationError( _("Sorry, accounts starting with ‘b‘ aren‘t welcome here."), code=‘no_b_users‘, ) class PasswordChangeForm[source]

用於用戶修改密碼的表單。

class PasswordResetForm[source]

用於生成並郵件發送重置密碼的一個一次性鏈接的表單。

send_email(subject_template_name, email_template_name, context, from_email, to_email[, html_email_template_name=None])?

New in Django 1.8.

使用這些參數來發送EmailMultiAlternatives。可以覆蓋這個方法,來自定義郵件如何發送給用戶。

參數:

subject_template_name —— 郵件標題的模板。

email_template_name —— 郵件正文的模板。

context —— 傳遞給subject_template、email_template 和html_email_template 的上下文(如果它不為None)。

from_email —— 發信人的地址。

to_email —— 收件人的地址。

html_email_template_name —— HTML 格式的郵件正文的模板;默認為None,這種情況下將發送純文本文件。

默認情況下,save() 方法向context 中添加的變量與password_reset() 向它的郵件上下文傳遞的變量相同。

class SetPasswordForm[source]

允許用戶不輸入舊密碼修改密碼的表單。

class UserChangeForm[source]

Admin 站點中使用的表單,用於修改用戶信息和權限。

class UserCreationForm[source]

用於創建新用戶的表單。

模板中的認證數據

當你使用RequestContext時,當前登入的用戶和它們的權限在模板上下文中可以訪問。

技術細節

技術上講,這些變量只有在你使用RequestContext並啟用了‘django.contrib.auth.context_processors.auth‘上下文處理器時才可以在模板上下文中訪問到。它是默認產生的配置文件。更多信息,參見RequestContext 文檔。

用戶

當渲染RequestContext模板時,當前登錄的用戶,可能是User實例或者AnonymousUser實例,會存儲在模板變量{{ user }}中:

<code>{% if user.is_authenticated %} 

<

p

>

Welcome, {{ user.username }}. Thanks for logging in.

p

>

{% else %}

<

p

>

Welcome, new user. Please log in.

p

>

{% endif %}/<code>

如果使用的不是RequestContext,則不可以訪問該模板變量:

權限

當前登錄的用戶的權限存儲在模板變量{{ perms }}中。這是個 django.contrib.auth.context_processors實例的封裝,他是一個對於模板友好的權限代理。

在{{ perms }} 對象中,單一屬性的查找是 User.has_module_perms的代理。如果已登錄的用戶在foo 應用中擁有任何許可,這個例子會顯示 True:

<code>{{ perms.foo }}/<code>

二級屬性的查找是User.has_perm的代理。如果已登錄的用戶擁有foo.can_vote的許可,這個示例會顯示True:

<code>{{ perms.foo.can_vote }}/<code>

所以,你可以用模板的{% if %}語句檢查權限:

<code>{% if perms.foo %}
    

<

p

>

You have permission to do something in the foo app.

p

>

{% if perms.foo.can_vote %}

<

p

>

You can vote!

p

>

{% endif %} {% if perms.foo.can_drive %}

<

p

>

You can drive!

p

>

{% endif %} {% else %}

<

p

>

You don‘t have permission to do anything in the foo app.

p

>

{% endif %}/<code>

還可以通過{% if in %}語句查詢權限。例如:

<code>{% if ‘foo‘ in perms %}
    {% if ‘foo.can_vote‘ in perms %}
        

In lookup works, too.

{%

endif

%} {%

endif

%}/<code>

在admin中管理用戶

如果django.contrib.admin和django.contrib.auth這兩個你都安裝了,將可以通過admin方便地查看和管理用戶、組和權限。可以像其它任何Django模型一樣創建和刪除用戶。可以創建組,並分配權限給用戶和組。admin中還會保存和顯示對用戶模型編輯的日誌。

創建用戶

在admin的主頁,你應該可以在“Auth”部分看到“Users”鏈接。“Add user” 頁面與標準admin頁面不同點在於它要求你在編輯用戶的其它字段之前先選擇一個用戶名和密碼。

另請注意:如果你想使得一個用戶能夠使用Django的admin站點創建其它用戶, 你需要給他添加用戶和修改用戶的權限(例如,"Add user” 和“Change user” 權限)。如果一個賬號具有添加用戶的權限但是沒有權限修改他們,該賬號將不能添加用戶。為什麼呢?因為如果你具有添加用戶的權限,你將可以添加超級用戶,這些超級用戶將可以修改其他用戶。所以Django同時要求添加權限和修改權限作為一種輕量的安全措施。

仔細考慮一下你是如何允許用戶管理權限的。如果你賦予了一個非超級用戶編輯用戶的能力,這和給他們超級用戶的權限在最終效果上是一樣的,因為他們將能夠提升他們自己下面的用戶的權限。

修改密碼

用戶密碼不會顯示在admin上(也不會存儲在數據庫中),但是會顯示密碼存儲的細節。 這個信息的顯示中包含一條指向修改密碼錶單的鏈接,允許管理員修改用戶的密碼。

Django認證系統


分享到:


相關文章: