django-使用者驗證系統,django-使用者驗證
django提供了一套使用者驗證系統,但是要使用這個系統,必須要使用django內建的使用者模型:django.contrib.auth.models.User,這個模型中預先定義了一些欄位,其中只有username和password是必須的。 username使用者名稱,該欄位是必須的,長度限制版本之間可能存在差異,1.10為150個字元以內(其他版本為30個字元,存在版本差異)。可以是字母、數字、+、-、_、.、@。這幾個字元。在1.10版本中,django正式支援utf-8的使用者名稱(也就是不受字元限制了),當然前提是要使用python3.x的版本。 當然,你也可以使用max_length、min_length等屬性來控制使用者名稱的長短限制。下面的欄位基本也適用。 django在1.10中實現了兩個驗證器,其會根據python版本自動選取,一般不用我們擔心。可以使用username_validator(New in Django 1.10.)屬性查看驗證器:預設 validators.UnicodeUsernameValidator於Python 3 、validators.ASCIIUsernameValidator於Python 2. 當然我們也可以改變驗證器,例如將python3的驗證器改成ASCII的:
from django.contrib.auth.models import Userfrom django.contrib.auth.validators import ASCIIUsernameValidatorclass CustomUser(User): username_validator = ASCIIUsernameValidator() class Meta: proxy = True # If no new field is added.
上面我們首先子類化了User model,然後改變了username_validator屬性,這也是標準的修改步驟。 password密碼,必須。django不會直接儲存原始密碼,而是儲存經過處理之後的雜湊值。所以在建立使用者或修改密碼的時候不能直接操作這個屬性,而是使用django提供的專門的方法,下面會再說明。 email可選,表示email地址。 first_name可選,30個字元以內(在中文環境中應該用不上) last_name可選,30個字元以內 groupsMany-to-many relationship to Group與Group屬於多對多的關係,而Group表示的是使用者組,由另一種表儲存。 user_permissionsMany-to-many relationship to Permission與Permission屬於多對多的關係,而Permission表示的是許可權,由另一種表儲存。關於許可權的問題需要另外說明,這裡暫時不討論。 is_active表使用者是否是活躍的,是一個布爾值。django提議與其刪除一個使用者的所有資訊,還不如將其設定為非活躍(即凍結)狀態。這樣不會破壞其他相關的外鍵關係,同時也擁有了後悔的可能。 注意:在1.10之前,django的後台驗證程式不會檢查使用者是否處於活躍狀態,也就是非活躍的使用者依然可以登入,此時要自己進行狀態驗證,例如:
if user.is_active: # 若使用者是活躍的,即未凍結的,在1.10之前凍結使用者預設也能登入,所以需要自己認證 login(request, user) # 登入 ...... #其他處理else: return HttpResponse('使用者被凍結')
在1.10版本中,django的預設驗證後台會拒絕凍結使用者的訪問了。當凍結的使用者登入時,會無法通過 authenticate(username=None, password=None, **kwargs) 的驗證,即該方法會返回None。 is_staff是否為staff身份,布爾值。擁有staff身份的使用者可以登入django的admin後台,且可以使用 staff_member_required(redirect_field_name='next', login_url='admin:login') 裝飾器來進行存取控制。詳情參考 django-存取控制 篇。 is_superuser是否是superuser身份,布爾值。擁有該身份的使用者將能夠登入admin後台,並擁有所有註冊模型的系統管理權限。 last_login使用者最後登入的時間。 date_joined使用者建立的時間。 以上就是django內建的使用者認證系統使用的模型的全部欄位了,也就是說django在資料庫中儲存的欄位資訊就是以上這些,如果需要擴充的話,有兩種方法: 1.另外再寫一個模型,用OneToOne的形式關聯到User中:
from django.db import modelsfrom django.contrib.auth.models import User class UserInfo(models.Model): user = models.OneToOneField(User) head_img = models.ImageField() # 其它擴充
2.另寫一個模型,直接繼承User:
from django.db import modelsfrom django.contrib.auth.models import User class UserInfo(User): head_img = models.ImageField() # 其它擴充
無論哪種方法都可以,因為那些已經定義好的欄位都是儲存在User表中的,而新增的欄位儲存在另外的表中,只是使用OneToOne的時候,查詢的入口略麻煩了些,詳情參考django的models。 使用者註冊: 所謂的使用者註冊,其實就是在User表中新建立一條記錄,而前面說過了,password欄位儲存的不是原始密碼,而是加密後的字串,所以不能直接對User對象的屬性進行修改,而是要調用專用的函數:
>>> from django.contrib.auth.models import User >>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
此時,使用者就已經建立
並放到資料庫中了,這個方法比較特別,其自動為我們儲存資料。 密碼修改: 由於密碼欄位不能直接操作,所以django也提供了函數專門用來修改密碼:
>>> from django.contrib.auth.models import User >>> u = User.objects.get(username='john')>>> u.set_password('new password') >>> u.save()
這裡有一個細節,它不像建立賬戶一樣會直接儲存的資料庫中,而是調用User對象的save()方法,表示將修改儲存到資料庫中。 資料修改: 其他的欄位可以通過直接修改對象屬性的方法來修改資料,然後調用儲存方法。 例如,我想修改使用者的email:
request.user.email = date['email'] # date的表單提交上來的資料request.user.save() # 儲存修改
一般資料修改需要使用者登入之後才能修改,而登入後的使用者可以是使用request.user來擷取當前登入的使用者,然後我們直接對其email屬性進行修改,資料來自於使用者提交的表單(你可以直接將其看成'scolia@example.com'這樣的直接的字面量)。最後我們調用其save方法,其實除了password相關的操作需要調用輔助函數之外,其他的基本都能這樣修改,這也是模型資料修改的典型方法。 使用者驗證: 要實現我們平常需要的驗證登入的功能,需要兩個步驟,第一步是驗證使用者名稱和密碼是否正確,第二步將使用者登入。
from django.contrib.auth import authenticate user = authenticate(username=date['user_name'], password=date['password'])
username和password兩個參數分別接受要登入使用者的使用者名稱和密碼,這裡傳的是明文。
若驗證通過,其會返回User對象,這個User對象記錄了所用的使用者資訊,你可以對這個對象進行資料的修改等之類的操作。
若登入失敗則返回None。 使用者登入: 驗證成功之後,就可以進行登入操作了,django提供了專門的登入函數來處理這個工作:
from django.contrib.auth import authenticate, login user = authenticate(username=date['user_name'], password=date['password'])if user is not None: login(request, user) #.....else: return HttpResponse('使用者名稱或密碼錯誤')
這裡的核心思想就是登入失敗後,返回的是None,而判斷到user不為None,即驗證成功了,就可以進行登入操作了,否則返回錯誤。 這裡詳細的瞭解一下login這個函數: login(request, user, backend=None) 其中request要求的是HttpRequest對象,也就是視圖的第一個參數所接受到的對象,習慣性的使用request,user要求要登入的User對象,也就是驗證成功後返回的User對象。backend是1.10中新增的,其作用是指定特點的背景程式,一般用不著,若有特殊需求可以參考django1.10的官方文檔。 由於HTTP協議是無狀態協議,所以使用的拓展的cookie和session首部來進行狀態記錄,django採用的是session,在登入成功後,django會給用戶端設定session首部,其一般是一個使用者的ID,而不是使用者的詳細資料。用戶端登入後訪問時都會回送這個ID,django接受到ID後找到對應的使用者,從而得知當前的訪問是哪個使用者。實現了登入的功能。 使用者登出: 上面說過使用者的狀態是通過session來記錄的,也就是將session設定為空白後,即丟失登入狀態,這就是登出了。django同樣提供了變數的函數來完成這個工作:
from django.contrib.auth import logout def logout_view(request): logout(request) # Redirect to a success page.
讓我們來認識一下這個函數: logout(request) 其接收的只有一個參數,也就是當前的request對象。其所完成的就是重設session的工作。如果使用者沒有登入,也不會報錯。 注意:這個還是會清空所有的session,也就是說如果你有不希望被刪除的session的話,要先擷取到相應的session,並在調用logout之後再將其收到添加進去。 這裡初步解釋了django中使用者驗證系統的使用,要擷取更多資訊可以查看官方文檔,或者個人提供了一份略微翻譯了的文檔:http://note.youdao.com/yws/public/redirect/share?id=b67cd6af80e4c59da71c47b85b5f3253&type=false