通過session,我們可以在多次瀏覽器請求中保持數據, 接下來的部分就是用session來處理用戶登錄了。 當然,不能僅憑用戶的一面之詞,我們就相信,所以我們需要認證。
當然了,Django 也提供了工具來處理這樣的常見任務(就像其他常見任務一樣)。 Django 用戶認證系統處理用戶帳號,組,權限以及基於cookie的用戶會話。 這個系統一般被稱為 auth/auth (認證與授權)系統。 這個系統的名稱同時也表明了用戶常見的兩步處理。 我們需要
1驗證 (認證) 用戶是否是他所宣稱的用戶(一般通過查詢數據庫驗證其用戶名和密碼)
2驗證用戶是否擁有執行某種操作的 授權 (通常會通過檢查一個權限表來確認)根據這些需求,Django 認證/授權 系統會包含以下的部分:
3用戶 : 在網站注冊的人
4權限 : 用於標識用戶是否可以執行某種操作的二進制(yes/no)標志
5 組 :一種可以將標記和權限應用於多個用戶的常用方法
6 Messages : 向用戶顯示隊列式的系統消息的常用方法
這些在admin的管理界面中都可以看到,只不過在admin中我們是通過后台系統直接管理這些用戶的。現在我們來看下如何通過User對象來進行管理
來進行測試下。首先我們在admin界面沒有進行登錄。我們進行測試
def function_test(request):
print request.user,request.user.is_authenticated()
得到的結果是:
AnonymousUser False
也就是個匿名用戶。且認證不通過。
然后我們緊接着在admin上進行登錄。這個時候的打印。得到登錄的用戶以及驗證通過的標識
zhf True
然后在瀏覽器上進行查看,發現多了一個sessionid,這表明在登錄成功后會存儲一個session值便於后續的識別
User實例從request.user獲得,下面來看下User實例有哪些屬性和方法
屬性:
Username:必需的,不能多於30個字符。 僅用字母數字式字符(字母、數字和下划線)。
first_name:可選; 少於等於30字符。
last_name:可選; 少於等於30字符
email:可選。 郵件地址。
Passwor: 必需的。 密碼的哈希值(Django不儲存原始密碼)。 See the Passwords section for more about this value.
is_staff: 布爾值。 用戶是否擁有網站的管理權限。
is_active: 布爾值. 設置該賬戶是否可以登錄。 把該標志位置為False而不是直接刪除賬戶
is_superuser: 布爾值 標識用戶是否擁有所有權限,無需顯式地權限分配定義。
last_login: 用戶上次登錄的時間日期。 它被默認設置為當前的日期/時間。
date_joined: 賬號被創建的日期時間 當賬號被創建時,它被默認設置為當前的日期/時間。
方法:
is_authenticated():對於真實的User對象,總是返回\ `` True`` 。 這是一個分辨用戶是否已被鑒證的方法。 它並不意味着任何權限,也不檢查用戶是否仍是活動的。 它僅說明此用戶已被成功鑒證
is_anonymous: 對於AnonymousUser`` 對象返回True(對於真實的User對象返回False) 總的來說,比起這個方法,你應該傾向於使用\is_authenticated()方法
get_full_name:返回first_name加上last_name,中間插入一個空格
set_password: 設定用戶密碼為指定字符串(自動處理成哈希串)。 實際上沒有保存User對象
check_password(passwd) : 如果指定的字符串與用戶密碼匹配則返回True。 比較時會使用密碼哈希表
get_group_permissions:返回一個用戶通過其所屬組獲得的權限字符串列表
get_all_permissions():返回一個用戶通過其所屬組以及自身權限所獲得的權限字符串列表
has_perm(perm):如果用戶有指定的權限,則返回True ,此時perm的格式是"package.codename"。如果用戶已不活動,此方法總是返回False
比如修改密碼,通常都是在admin后台界面完成,不過也可以通過程序修改密碼。使用set_password()
from django.contrib.auth.models import User
u = User.objects.get(username='zhf')
u.set_password('new password')
u.save()
介紹完了User對象實例,我們來看下再登錄方面的應用
登錄:
login():
從視圖中登入一個用戶,請使用login()。它接受一個HttpRequest對象和一個User對象。login()使用Django的session框架來將用戶的ID保存在session中。注意任何在匿名會話中設置的數據都會在用戶登入后的會話中都會記住。
下面的示例演示如何使用authenticate()和login():建立一個簡單的用戶登錄系統:
login.html:
<form action="/login/" method = 'post'>
{% csrf_token %}
<div>
用戶名:<input type="text" class="form-control" name="username" placeholder="請輸入用戶名">
</div>
<div>
密碼:<input type="text" class="form-control" name="password" placeholder="請輸入密碼">
</div>
<div>
<input type="submit" value = "ok"/>
</div>
</form>
Index1.html:
<div>
<h1>welcome {{username}}</h1>
<a href="/logout">logout</a>
</div>
Views.py中的處理函數:
from django.contrib import auth
def login(request):
username=request.POST['username']
password=request.POST['password']
user=auth.authenticate(username=username,password=password)
if user is not None and user.is_active:
auth.login(request,user)
return HttpResponseRedirect("/index1/")
else:
return HttpResponse('error user')
def logout(request):
auth.logout(request)
return HttpResponseRedirect("/index1/")
def index1(request):
print request.session.get('_auth_user_hash')
print request.session.get('_auth_user_backend')
print request.session.get('_auth_user_id')
user=request.user
return render(request,'index.html',{'username':str(user)})
首先進入登錄界面。輸入用戶名和密碼
會自動跳轉到index1的界面顯示登錄的用戶名
對應的sessionid
點擊logout后退出
此時的sessionid也同時被刪除了
來看下代碼的運行過程:
1 首先在login之前調用authenticate進行認證。
2 認證通過后運行login函數,login函數的作用是將用戶名寫入session中並生成sessionid發送給客戶端
3 logout的作用就是清空對應session的數據
前面介紹了用戶的登錄過程,如果用戶已經登錄,那么就可以查看網站對於注冊用戶開放的權限,如果是未登錄,再查看這些內容的時候就必須先跳到登錄的界面進行登錄后才可以。也就是我們必須限制用戶對於頁面的訪問。最簡單的方法就是在每個頁面的處理函數中加入驗證功能。當沒有登錄的時候,重定向登錄的界面進行登錄
def my_view(request):
if not request.user.is_authenticated():
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
但每個函數都加上這個判斷也太麻煩了,幸好django給我們提供了裝飾器函數login_required。
@login_required()
def preview(request):
return render(request,'content.html')
login_required()完成下面的事情:
1 如果用戶沒有登入,則重定向到settings.LOGIN_URL,並將當前訪問的絕對路徑傳遞到查詢字符串中。例如:/accounts/login/?next=/polls/3/。LOGIN_URL默認為/accounts/login
2如果用戶已經登入,則正常執行視圖。視圖的代碼可以安全地假設用戶已經登入。
我們來進行測試下,首先沒有用戶登錄。這個”打開目錄”鏈接的處理函數就是被login_required裝飾的preview函數
登錄后頁面跳轉到/accounts/login/?next=/preview/。並且網頁提示/accounts/login/找不到
原因在於login_required模式是重定向到/accounts/login/?next=/polls/3/的路徑。如果我們想改變這個路徑有兩個方法:
1 在settings.py中添加我們需要的URL地址,例如LOGIN_URL = '/show_login/'
2 在裝飾器中添加login_url路徑
@login_required(login_url='/show_login/')
def preview(request):
return render(request,'content.html')
添加后可以看到就跳轉到我們自己自定義的登錄界面上去了
默認情況下,在成功認證后用戶應該被重定向的路徑存儲在查詢字符串的一個叫做"next"的參數中。如果對該參數你傾向使用一個不同的名字,login_required()帶有一個可選的redirect_field_name參數:
@login_required(login_url='/show_login/',redirect_field_name='para')
def preview(request):
return render(request,'content.html')
那么最后來看下如果用戶已經登錄的情況下的處理
點擊打開目錄,此時直接鏈接到preview,並返回具體內容
Django提供了很多的認證功能,除了登錄驗證,還有用戶權限判斷。具體的功能使用參考文檔:
http://python.usyiyi.cn/documents/django_182/topics/auth/default.html#