Django元件之使用者認證和中介軟體
使用者認證元件
功能:用session記錄登入驗證狀態
前提:使用者表 django自帶的auth_user
建立超級使用者python manage.py createsuperuser
API 如下
一、 auth模組
1: from django.contrib import auth
django.contrib.auth中提供了許多方法,這裡主要介紹其中的三個
1.1 authenticate()
提供了使用者認證,即驗證使用者名稱以及密碼是否正確,一般需要username password兩個關鍵字引數</p>如果認證資訊有效,會返回一個 User 物件。
authenticate()會在User 物件上設定一個屬性標識那種認證後端認證了該使用者,且該資訊在後面的登入過程中是需要的。
當我們試圖登陸一個從資料庫中直接取出來不經過authenticate()的User物件會報錯的!!
1: user = authenticate(username='someone',password='somepassword')
1.2 login(HttpRequest, user)
該函式接受一個HttpRequest物件,以及一個認證了的User物件
此函式使用django的session框架給某個已認證的使用者附加上session id等資訊。
1: def my_view(request):
2: username = request.POST['username']3: password = request.POST['password']4: user = authenticate(username=username, password=password)
5: if user is not None:6: login(request, user)
7: # Redirect to a success page.8: else:9: pass10: # Return an 'invalid login' error message.11:
1.3 logout(request) 登出使用者
1: from django.contrib.auth import logout
2: def logout_view(request):
3: logout(request)4: # Redirect to a success page.
該函式接受一個HttpRequest物件,無返回值。當呼叫該函式時,當前請求的session資訊會全部清除。該使用者即使沒有登入,使用該函式也不會報錯。
二、User物件
User 物件屬性:username, password(必填項)password用雜湊演算法儲存到資料庫.
2.1 user物件的 is_authenticated()
如果是真正的 User 物件,返回值恆為 True 。 用於檢查使用者是否已經通過了認證。
通過認證並不意味著使用者擁有任何許可權,甚至也不檢查該使用者是否處於啟用狀態,這只是表明使用者成功的通過了認證。
這個方法很重要, 在後臺用request.user.is_authenticated()判斷使用者是否已經登入,如果true則可以向前臺展示request.user.name
現在有如下要求:
1 使用者登陸後才能訪問某些頁面,
2 如果使用者沒有登入就訪問該頁面的話直接跳到登入頁面
3 使用者在跳轉的登陸介面中完成登陸後,自動訪問跳轉到之前訪問的地址
方法1:
1: def my_view(request):
2: if not request.user.is_authenticated():3: return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))4:
方法2:
django已經為我們設計好了一個用於此種情況的裝飾器:@login_requierd
1: from django.contrib.auth.decorators import login_required
2: @login_required3: def my_view(request):
4: pass5:
若使用者沒有登入,則會跳轉到django預設的 登入URL '/accounts/login/ ' (這個值可以在settings檔案中通過LOGIN_URL進行修改)。並傳遞 當前訪問url的絕對路徑 (登陸成功後,會重定向到該路徑)。
2.2 建立使用者
1: from django.contrib.auth.models import User
2: user = User.objects.create_user(username='',password='',email='')
2.3 check_password(password)
使用者需要修改密碼的時候 首先要讓他輸入原來的密碼 ,如果給定的字串通過了密碼檢查,返回 True
2.4 修改密碼
1: user = User.objects.get(username='')
2: user.set_password(password='')
3: user.save()
4:
2.5 簡單示例
註冊
1: def sign_up(request):
2: state = None3: if request.method == 'POST':
4: password = request.POST.get('password', '')5: repeat_password = request.POST.get('repeat_password', '')6: email=request.POST.get('email', '')7: username = request.POST.get('username', '')8: if User.objects.filter(username=username):
9: state = 'user_exist'10: else:
11: new_user = User.objects.create_user(username=username, password=password,email=email)12: new_user.save()13: return redirect('/book/')
14: content = {15: 'state': state,16: 'user': None,
17: }18: return render(request, 'sign_up.html', content)
19:
修改密碼:
1: @login_required2: def set_password(request):
3: user = request.user4: state = None5: if request.method == 'POST':
6: old_password = request.POST.get('old_password', '')7: new_password = request.POST.get('new_password', '')8: repeat_password = request.POST.get('repeat_password', '')9: if user.check_password(old_password):10: if not new_password:
11: state = 'empty'12: elif new_password != repeat_password:13: state = 'repeat_error'14: else:
15: user.set_password(new_password)
16: user.save()
17: return redirect("/log_in/")18: else:
19: state = 'password_error'20: content = {21: 'user': user,22: 'state': state,23: }24: return render(request, 'set_password.html', content)
25:
補充:
匿名使用者的特徵:
Id永遠為none,username永遠為空字串,get_username()永遠返回空字串,is_staff和is_superuser永遠為false,is_active永遠為False……
總的來說不是空就是flase。
中介軟體
Middleware
中介軟體顧名思義,是介於request與response處理之間的一道處理過程,相對比較輕量級,並且在全域性上改變django的輸入與輸出。因為改變的是全域性,所以需要謹慎實用,用不好會影響到效能。
如果你想修改請求,例如被傳送到view中的HttpRequest物件。 或者你想修改view返回的HttpResponse物件,這些都可以通過中介軟體來實現。
可能你還想在view執行之前做一些操作,這種情況就可以用 middleware來實現。
Django有預設的Middleware,每一箇中間件都有具體的功能。
自定義中介軟體
中介軟體中一共有四個方法:
process_request
process_view
process_exception
process_response
當用戶發起請求的時候會依次經過所有的的中介軟體,這個時候的請求時process_request,最後到達views的函式中,views函式處理後,在依次穿過中介軟體,這個時候是process_response,最後返回給請求者。
上述截圖中的中介軟體都是django中的,我們也可以自己定義一箇中間件,我們可以自己寫一個類,但是必須繼承MiddlewareMixin
匯入
1: from django.utils.deprecation import MiddlewareMixin
1: from django.utils.deprecation import MiddlewareMixin
2: from django.shortcuts import HttpResponse
3:4: class Md1(MiddlewareMixin):
5: def process_request(self,request):
6: print("Md1請求")7: def process_response(self,request,response):
8: print("Md1返回")9: return response
10: class Md2(MiddlewareMixin):
11: def process_request(self,request):
12: print("Md2請求")13: #return HttpResponse("Md2中斷")14: def process_response(self,request,response):
15: print("Md2返回")16: return response
意:如果當請求到達請求2的時候直接不符合條件返回,即return HttpResponse("Md2中斷"),程式將把請求直接發給中介軟體2返回,然後依次返回到請求者
流程圖如下:
process_view
1: process_view(self, request, callback, callback_args, callback_kwargs)
流程圖如下:
當最後一箇中間的process_request到達路由關係對映之後,返回到中介軟體1的process_view,然後依次往下,到達views函式,最後通過process_response依次返回到達使用者。
process_view可以用來呼叫檢視函式:
1: class Md1(MiddlewareMixin):
2: def process_request(self,request):
3: print("Md1請求")4: #return HttpResponse("Md1中斷")5: def process_response(self,request,response):
6: print("Md1返回")7: return response
8: def process_view(self, request, callback, callback_args, callback_kwargs):
9: # return HttpResponse("hello")10: response=callback(request,*callback_args,**callback_kwargs)11: return response
12:
注意:process_view如果有返回值,會越過其他中介軟體的process_view以及檢視函式,但是所有的process_response都還會執行
process_exception
1: process_exception(self, request, exception)
流程圖如下:
當views出現錯誤時:
示例:
1: class Md1(MiddlewareMixin):
2: def process_request(self,request):
3: print("Md1請求")4: #return HttpResponse("Md1中斷")5: def process_response(self,request,response):
6: print("Md1返回")7: return response
8: def process_view(self, request, callback, callback_args, callback_kwargs):
9: # return HttpResponse("hello")10: # response=callback(request,*callback_args,**callback_kwargs)11: # return response
12: print("md1 process_view...")13: def process_exception(self):
14: print("md1 process_exception...")15: class Md2(MiddlewareMixin):
16: def process_request(self,request):
17: print("Md2請求")18: # return HttpResponse("Md2中斷")19: def process_response(self,request,response):
20: print("Md2返回")21: return response
22: def process_view(self, request, callback, callback_args, callback_kwargs):
23: print("md2 process_view...")24: def process_exception(self):
25: print("md1 process_exception...")26:
列印結果如下
1: Md1請求2: Md2請求3: md1 process_view...4: md2 process_view...5: view函式...6:7: Md2返回8: Md1返回
將md2的process_exception修改如下:
1: def process_exception(self, request, exception):2: print("md2 process_exception...")3: return HttpResponse("error")4:
結果如下:
1: Md1請求2: Md2請求3: md1 process_view...4: md2 process_view...5: view函式...6: md2 process_exception...7: Md2返回8: Md1返回9:
中介軟體應用案例
1、做IP訪問頻率限制
某些IP訪問伺服器的頻率過高,進行攔截,比如限制每分鐘不能超過20次。
2、URL訪問過濾
如果使用者訪問的是login檢視(放過)
如果訪問其他檢視,需要檢測是不是有session認證,已經有了放行,沒有返回login,這樣就省得在多個檢視函式上寫裝飾器了!
程式碼示例
1: from django.utils.deprecation import MiddlewareMixin
2: from django.shortcuts import redirect
3: from authDemo import settings
4:5: class AuthMiddleware(MiddlewareMixin) :
6:7: def process_request(self, request) :
8: # 新增一個url白名單9: white_list = settings.WHITE_LIST10: if request.path in white_list :11: return None
12:13: if not request.user.is_authenticated :14: return redirect("/login/")15: