標籤:clean reg log ... war 建立 username dex user
Django內建的使用者認證
我們在開發一個網站的時候,無可避免的需要設計實現網站的使用者系統,此時我們需要實現包括使用者註冊,使用者登入,使用者認證,登出,修改密碼等功能,這真是一個麻煩的事情。
django作為一個完美主義者的終極架構,當然也會想到使用者的這些疼點,因此它內建了強大的使用者認證系統--auth,它預設使用auth_user表來儲存使用者資料。
auth模組
auth本質就是一個django的app,裡面也有views,models等。
from django.contrib import auth
auth中提供了很多實用方法:
authenticate()
提供了使用者認證功能,即驗證使用者名稱以及密碼是否正確,一般需要username,password兩個關鍵字參數。
如果認證成功(使用者名稱和密碼正確有效),便會返回一個User對象。
authenticate()會在該user對象上設定一個屬性來標識後端已經認證了該使用者,且該資訊在後續的登入過程中是需要的。
用法:
from django.contrib import authuser_obj = auth.authenticate(request, username=‘china‘, password=‘bigcountry‘)註:預設是校正auth_user表,而其中的欄位名是username,password,如果是自訂的欄位,就無需一定用username,password了。
login(HttpRequest, user_obj)
該函數接受一個httpRequest對象,以及一個經過認證的user對象。
該函數實現一個使用者登入的功能,它本質上會在後端為該使用者產生相關session資料。
from django.contrib.auth import authenticate, logindef my_view(request): username = request.POST.get(‘username‘) password = request.POST.get(‘password‘) user = authenticate(request, username=username, password=passwrod) if user is not None: login(request, user) # 跳轉到登入成功後的頁面 else: # 返回一個登入失敗的資訊
logout(request)
該函數接受一個httprequest對象,無傳回值
當調用該函數時,當前請求的session資訊會全部清除。該使用者即使沒有登入,使用該函數也不會報錯。
用法:
from django.contrib.auth import logoutdef logout_view(request): logout(request) # 跳轉到登出後預設定的頁面,如登入頁面或首頁
is_authenticated()
用來判斷當前請求是否通過了認證。
用法:
def my_view(request): if not request.user.is_authenticated(): return redirect("{}?next={}".format(settings.LOGIN_URL, request.path))login_requierd()
auth給我們提供的一個裝飾器工具,用來快捷的給某個視圖添加登入校正。
用法:
from django.contrib.auth.decorators import login_required@login_requireddef home(request): pass
若使用者沒有登入,則會跳轉到django預設的登入URL “/accounts/login/” 並傳遞當前訪問url的絕對路勁(登陸成功後,會重新導向到該路徑)。
如果需要自訂登入的url,則需要在settings.py檔案中通過LOFIN_URL進行修改。!!!
樣本:
LOGIN_URL= ‘/login/’ # 這裡配置成你項目登入頁面的路由
create_user()
auth提供的一個建立新使用者的方法,需要提供必要參數(username,password)等。
用法:
from django.contrib.auth.models import Useruser = User.objects.create_user(username=‘使用者名稱‘, password=‘密碼‘, email=‘郵件‘,...)
create_superuser()
auth提供的一個建立新的超級使用者的方法(管理員),需要提供必要參數(username,password, email)等。
from django.contrib.auth.models import Useruser = User.objects.create_superuser(username=‘使用者名稱‘, password=‘密碼‘, email=‘郵件‘,...)
# 必須提供郵箱,預設是以郵箱當登入名稱的
check_password(password)
auth提供的一個檢查密碼是否正確的方法,需要提供當前請求使用者的密碼。
密碼正確返回True,否則返回False。
用法:
flag = user_obj.check_password(‘密碼‘)
set_password(password)
auth 提供的一個修改密碼的方法,接收要設定的新密碼作為參數。
注意:設定完一定要調用使用者物件的save方法!!!
用法:
user.set_password(password=‘new_password‘)user.save()
一個修改密碼功能的簡單樣本
from django.contrib.auth.decorators import login_required@login_requireddef set_password(request): user = request.user err_msg= ‘‘ content = {“err_msg”: err_msg} if request.method == ‘POST‘: old_password = request.POST.get(‘old_password‘, ‘‘) new_password = request.POST.get(‘new_password‘,‘‘) repeat_password = request.POST.get(‘repeat_password‘) # 檢查舊密碼是否正確 if user.check_password(old_password): if not new_password: err_msg = ‘新密碼不可為空‘ elif new_password != repeat_password: err_msg = ‘修改的密碼兩次不一致‘ else: user.set_password(new_password) user.save() return redirect(‘/login/‘) else: err_msg = ‘原密碼輸入錯誤‘ return render(request, ‘set_password.html‘, content)User對象的屬性
User對象屬性:username, password
is_staff : 使用者是否擁有網站的系統管理權限
is_active: 是否允許使用者登入,設定為False, 可以在不刪除使用者的前提下禁止使用者登入
擴充預設的auth_user表!!!
雖然內建的認證系統很好用,但auth_user表欄位都是固定的那幾個,我們在項目中沒法拿來直接使用,如果想加一個儲存使用者手機號的欄位,how to do?
也許你可能會想到建立另外一張表然後通過一對一和內建的auth_user表關聯,這樣雖然能滿足要求,但還是有點麻煩。
因此django為我們提供了自訂user表的方式,只需繼承內建的AbstractUser類,來定義一個自己的Model類。
這樣既能根據項目需求靈活的設計使用者表,又能使用Django強大的認證系統了。
------app的models.py檔案中from django.contrib.auth.models import AbstractUserclass UserInfo(AbstractUser): """ 使用者資訊表 """ nid = models.AutoField(primary_key=True) phone = models.CharField(max_length=11, null=True, unique=True) def __str__(self): return self.username
注意:
按上面的方式擴充了內建的auth_user表之後,一定要在settings.py中告知django,我們現在使用的是我們新定義的UserInfo表來做使用者認證,寫法如下:
# 引用Django內建的User表,繼承使用時需要設定AUTH_USER_MODEL = ‘app名.UserInfo‘
Ps: 一旦我們指定了新的認證系統所使用的表,我們就需要重新在資料庫中建立該表,而不能繼續使用原來預設的auth_user表了。
1 auth組件 2 3 建立使用者,驗證登入 4 5 from django.contrib import auth 6 7 auth_user 表: 8 is_staff 是否是職員的狀態,指定使用者是否可以登入管理後台 9 is_active10 is_superuser11 12 建立超級管理員13 python manage.py createsuperuser14 15 認證使用者16 user_obj = auth.authenticate(request, username=username, password= password)17 18 認證通過,就返回一個user對象,錯誤就返回none19 20 記錄登入狀態21 實際建立session, 故auth中介軟體,依賴session中介軟體,故session中介軟體註冊順序需在前,22 auth.login(request,user_obj)23 24 登出,刪除session25 auth.logout(request)26 27 查看使用者登入狀態28 request.user.is_authenticaed() 返回false 或true29 30 django登入認證裝飾器31 from django.contrib.auth.decorators import login_required32 33 @login_required34 def index(request):pass 直接載入視圖上,就可以運行前先認證35 36 django預設當使用者訪問某一頁面時,沒有登入,則會跳轉到登入url並且儲存之前的url,等登入後跳轉37 要求標頭:Location: /accounts/login/?next=/index/38 39 上面是預設要跳轉到 /accounts/login/ 故如果想用預設的必須url改成/accounts/login/40 這樣的url設計不方便,故可以在setting中自己設定41 42 LOGIN_URL = ‘/login/‘ # 這裡配置成你項目登入頁面的路由43 44 45 46 ‘django.contrib.auth.middleware.AuthenticationMiddleware‘,47 沒有登入就沒有session,該中介軟體就返回一個匿名對象,為瞭解決調用方法不報錯48 49 request.user 主要是用於上面的中介軟體,進入到該中介軟體,50 主要定義了一個process_request()的方法,主要是在視圖之前做的事51 52 !!!!request.user 最後時返回一個user對象或匿名對象
小結一個註冊的樣本
from django.contrib import auth#建立普通使用者:(註冊樣本)def signup(request): re_form_obj = RegisterForm() if request.method == ‘POST‘: re_form_obj = RegisterForm(request.POST) if re_form_obj.is_valid(): # 驗證form對象, 而驗證user表即auth表指定的欄位,如賬戶秘密可以用 auth.authenticate(username=,password=,) 之所以要username,password是因為用的是預設的auth表,其中使用者名稱和密碼欄位名分別為username,password # name = form_obj.cleaned_data.get(‘username‘) # 驗證通過後才能擷取到欄位 # paw = form_obj.cleaned_data.get(‘password‘) # User.objects.create(username=name,password=pwd) 這種建立的是明文的密碼,這種是無法登入的,因為django驗證是按密文驗證的,故需要用django提供的加密的方式建立使用者,如下 # User.objects.create_user(username=name,password=pwd) # 或 User.objects.create_user(**form_obj.cleaned_data) # 所有索引值對字典打散,寫入資料庫 擴充:註冊完成之後,可以通過背景方式,實現自動登入,如下代碼 user_obj = auth.authenticate(**form_obj.cleaned_data) auth.login(request,user_obj) # 建立session return redirect(‘/index/‘) # 或則後台發json資料給前台,前台通過ajax接收,渲染到頁面,實現自動登入和幾秒中跳轉
Django架構-Auth組件