django認證系統(tǒng) Authentication使用詳解
前言
Django自帶一個用戶認證系統(tǒng),用于處理用戶賬戶、群組、許可和基于cookie的用戶會話。
Django的認證系統(tǒng)包含了身份驗證和權限管理兩部分。簡單地說,身份驗證用于核實某個用戶是否合法,權限管理則是決定一個合法用戶具有哪些權限。往后,‘認證'這個詞同時代指上面兩部分的含義。
Django的認證系統(tǒng)主要包括下面幾個部分:
- 用戶
- 許可
- 組
- 可配置的密碼哈希系統(tǒng)
- 用于用戶登錄或者限制訪問的表單和視圖工具
- 可插拔的后臺系統(tǒng)
類似下面的問題,不是Django認證系統(tǒng)的業(yè)務范圍,請使用第三方工具:
- 密碼強度檢查
- 登錄請求限制
- 第三方認證
默認情況下,使用django-admin startproject命令后,認證相關的模塊已經(jīng)自動添加到settings文件內(nèi)了,如果沒有的話,請手動添加。
在INSTALLED_APPS配置項中添加:
- 'django.contrib.auth': 包含認證框架的核心以及默認模型
- 'django.contrib.contenttypes':內(nèi)容類型系統(tǒng),用于給模型關聯(lián)許可
在MIDDLEWARE配置項中添加:
- SessionMiddleware:通過請求管理會話
- AuthenticationMiddleware:將會話和用戶關聯(lián)
當配置正確后,運行manage.py migrate命令,創(chuàng)建用戶認證系統(tǒng)相關的數(shù)據(jù)庫表以及分配預定義的權限。
一、用戶對象
用戶對象是Django認證系統(tǒng)的核心!在Django的認證框架中只有一個用戶模型也就是User模型,它位于django.contrib.auth.models。
本節(jié)內(nèi)容敘述的所有功能,都是基于這個User模型的,和這個User模型沒有任何關系的自定義用戶模型是無法使用Django認證系統(tǒng)的功能的!
用戶模型主要有下面幾個字段:
- username
- password
- first_name
- last_name
1. 創(chuàng)建用戶
要創(chuàng)建一個新用戶,最直接的辦法是使用create_user()方法:
>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
# 這時,user是一個User類的實例,已經(jīng)保存在了數(shù)據(jù)庫內(nèi),你可以隨時修改它的屬性,例如:
>>> user.last_name = 'Lennon'
>>> user.save()
如果你已經(jīng)啟用了Django的admin站點,你也可以在后臺創(chuàng)建用戶。
2. 創(chuàng)建超級用戶
使用createsuperuser命令,創(chuàng)建超級用戶:
$ python manage.py createsuperuser
或者
$ python manage.py createsuperuser --username=joe --email=joe@example.com
根據(jù)提示輸入名字、密碼和郵箱地址。密碼要有一定強度
3. 修改密碼
Django默認會對密碼進行加密,因此,不要企圖對密碼進行直接操作。
要修改密碼,有兩個辦法:
- 使用命令行: python manage.py changepassword username。如果不提供用戶名,則會嘗試修改當前系統(tǒng)用戶的密碼。
- 使用set_password()方法:
from django.contrib.auth.models import User
u = User.objects.get(username='john')
u.set_password('new password')
u.save()
同樣可以在admin中修改密碼。Django提供了views和forms,方便用戶自己修改密碼。 修改密碼后,用戶的所有當前會話將被注銷。
4. 用戶驗證
利用authenticate()方法,對用戶進行驗證。該方法通常接收username與password作為參數(shù)。要注意的是,認證的后端可能有好幾個,有一項認證通過則返回一個User類對象,一項都沒通過或者拋出了PermissionDenied異常,則返回一個None。例如:
from django.contrib.auth import authenticate user = authenticate(username='john', password='secret') if user is not None: # A backend authenticated the credentials else: # No backend authenticated the credentials
二、 權限與授權
Django提供了一個簡單的權限系統(tǒng),并且已經(jīng)用于它的admin站點,當然你也可以在你的代碼中使用。
User模型的對象有兩個多對多的字段:groups和user_permissions,可以像下面這樣訪問他們:
myuser.groups.set([group_list]) myuser.groups.add(group, group, ...) myuser.groups.remove(group, group, ...) myuser.groups.clear() myuser.user_permissions.set([permission_list]) myuser.user_permissions.add(permission, permission, ...) myuser.user_permissions.remove(permission, permission, ...) myuser.user_permissions.clear()
1. 默認權限
默認情況下,使用manage.py migrate命令時,Django會給每個已經(jīng)存在的model添加默認的權限。 假設你現(xiàn)在有個app叫做foo,有個model叫做bar,使用下面的方式可以測試默認權限:
add: user.has_perm('foo.add_bar')
change: user.has_perm('foo.change_bar')
delete: user.has_perm('foo.delete_bar')
2. 用戶組
Django提供了一個django.contrib.auth.models.Group模型,該model可用于給用戶分組,實現(xiàn)批量管理。用戶和組屬于多對多的關系。用戶自動具有所屬組的所有權限。
3. 在代碼中創(chuàng)建權限
例如,為myapp中的BlogPost模型添加一個can_publish權限。
from myapp.models import BlogPost from django.contrib.auth.models import 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, )
然后,你可以通過User模型的user_permissions屬性或者Group模型的permissions屬性為用戶添加該權限。
4. 權限緩存
權限檢查后,會被緩存在用戶對象中。參考下面的例子:
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
# Be aware that user.refresh_from_db() won't clear the cache.
user = get_object_or_404(User, pk=user_id)
# Permission cache is repopulated from the database
user.has_perm('myapp.change_bar') # True
...
三、 在視圖中認證用戶
Django使用session和中間件關聯(lián)請求對象中和認證系統(tǒng)。
每一次請求中都包含一個request.user屬性,表示當前用戶。如果該用戶未登陸,該屬性的值是一個AnonymousUser實例(匿名用戶),如果已經(jīng)登錄,該屬性就是一個User模型的實例。
可以使用is_authenticated方法進行判斷,如下:
if request.user.is_authenticated: # Do something for authenticated users. ... else: # Do something for anonymous users. ...
1. 如何登錄用戶
在視圖中,使用認證系統(tǒng)的login()方法登錄用戶。它接收一個HttpRequest參數(shù)和一個User對象參數(shù)。該方法會把用戶的ID保存在Django的session中。下面是一個認證和登陸的例子:
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:
login(request, user)
# 跳轉到成功頁面
...
else:
# 返回一個非法登錄的錯誤頁面
...
2. 如何注銷用戶
logout(request)[source]:
from django.contrib.auth import logout def logout_view(request): logout(request) # Redirect to a success page.
注意,被logout的用戶如何沒登錄,不會拋出錯誤。 一旦logout,當前請求中的session數(shù)據(jù)都會被清空。
3. 限制用戶的訪問權限
很多時候,我們要區(qū)分已登錄用戶和未登錄用戶,只對登錄的用戶開放一些頁面或功能,限制未登錄用戶的行為。辦法有很多,下面是主要幾種:
1.原始的辦法:
如果用戶未登錄,重定向到登錄頁面,如下所示:
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')
# ...
2. 使用裝飾器
原型:login_required(redirect_field_name='next', login_url=None)[source]
被該裝飾器裝飾的視圖,強制要求用戶必須登錄后才可以訪問。
from django.contrib.auth.decorators import login_required @login_required def my_view(request): ...
該裝飾器工作機制:
- 如果用戶未登陸,重定向到settings.LOGIN_URL,傳遞當前絕對路徑作為url字符串的參數(shù),例如:/accounts/login/?next=/polls/3/
- 如果用戶已經(jīng)登錄,執(zhí)行正常的視圖
此時,默認的url中使用的參數(shù)是“next”,如果你想使用自定義的參數(shù),請修改login_required()的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變量。
login_required()裝飾器還有一個可選的longin_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和登陸視圖保持正確的關聯(lián)。例如:
from django.contrib.auth import views as auth_views url(r'^accounts/login/$', auth_views.login),
3. 使用LoginRequired mixin
通過繼承LoginRequiredMixin類的方式限制用戶。在多繼承時,該類必須是最左邊的父類。
from django.contrib.auth.mixins import LoginRequiredMixin class MyView(LoginRequiredMixin, View): login_url = '/login/' redirect_field_name = 'redirect_to'
4. 進行測試,根據(jù)結果決定動作
也可以直接在視圖中進行過濾:
from django.shortcuts import redirect
def my_view(request):
if not request.user.email.endswith('@example.com'):
return redirect('/login/?next=%s' % request.path)
# ...
上面根據(jù)用戶的郵箱地址,判斷用戶的權限。
5. 使用權限需求裝飾器
Django內(nèi)置了一個permission_required()裝飾器,用戶根據(jù)用戶權限,決定視圖的訪問權限,如下所示:
from django.contrib.auth.decorators import permission_required
@permission_required('polls.can_vote')
def my_view(request):
...
權限的格式是<app label>.<permission codename>。
該裝飾器還有一個可選的longin_url參數(shù):
from django.contrib.auth.decorators import permission_required
@permission_required('polls.can_vote', login_url='/loginpage/')
def my_view(request):
...
4. 認證視圖
Django為我們提供了一系列認證相關的視圖,可以直接拿來用,這樣你就不需要自己寫登錄、注銷、注冊等視圖。但是,但是,Django沒有為認證視圖提供默認的模板,你需要自己寫......。
所以,除非懶癌發(fā)作,還是老老實實自己寫認證相關的視圖、路由和模板吧。個人認為類似跟實際生產(chǎn)環(huán)境結合非常緊密的視圖,根本不需要這種雞肋的內(nèi)置視圖,到最后,你發(fā)現(xiàn)還是要自己寫才能滿足需求。
所以,后面的部分就不贅述了!
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Django1.7+python 2.78+pycharm配置mysql數(shù)據(jù)庫教程
原本感覺在Django1.7+python 2.78+pycharm環(huán)境下配置mysql數(shù)據(jù)庫是件很容易的事情,結果具體操作的時候才發(fā)現(xiàn),問題還是挺多的,這里記錄一下最終的配置結果,給需要的小伙伴參考下吧2014-11-11
Selenium+BeautifulSoup+json獲取Script標簽內(nèi)的json數(shù)據(jù)
這篇文章主要介紹了Selenium+BeautifulSoup+json獲取Script標簽內(nèi)的json數(shù)據(jù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12
Appium+python+unittest搭建UI自動化框架的實現(xiàn)
本文主要介紹了Appium+python+unittest搭建UI自動化框架的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-03-03
Python學習教程之常用的內(nèi)置函數(shù)大全
python給我們提供了很多已經(jīng)定義好的函數(shù),下面這篇文章主要給大家介紹了關于Python學習教程之一些常用的內(nèi)置函數(shù),文中分享了關于數(shù)學函數(shù)、功能函數(shù)、類型轉換函數(shù)、字符串處理和序列處理函數(shù)的相關資料,需要的朋友可以參考借鑒,下面來一起看看吧。2017-07-07

