django 自定義登陸驗證邏輯

本文的django view採用的是基於cbv的模式html

django中的登陸功能主要涉及到django.contrib.auth這個包,它提供了2個重要的函數:authenticate和login。數據庫

django.contrib.auth.authenticate

這個函數接受的一個收集參數,但至少須要接受username和password這兩個關鍵參數,它完成如下的事情:django

  1. 從setting中獲取AUTHENTICATION_BACKENDS的元組, 默認狀況下是django.contrib.auth.backends.ModelBackend.
  2. 遍歷這整個元組,而後調用每個Backend的authenticate方法,而每一個Backend.authenticate會有一個登錄邏輯(自定義後面會說起),如ModelBackend.authenticate它拿傳過來的帳號密碼的與數據庫user model的username與password進行驗證。
  3. 若是Backend.authenticate驗證經過,就會返回一個user對象,而後auth.authenticate將再也不進行遍歷,return user對象。若是返回None,就繼續調用下一個Backend.authenticate。若是所有都返回None,那麼驗證不經過。

django.contrib.auth.login

login只會用在auth.authenticate返回一個user的狀況下,這個函數會接着作下面的事情:bash

  1. 生成一個新的session_id 放到request.session中(這個session在返回時會被session的中間件進行處理,將session_id放入到cookie當中)
  2. 將這個user放到request.user中

講了那麼多,咱們來看一下代碼:cookie

class LoginView(View):
	def get(self, request):
		pass

	def post(self, request):
		username = request.POST.get('username', '')
		password = request.POST.get('password', '')
		login_form = LoginForm(request.POST)
		if login_form.is_valid:
			user = auth.authenticate(username=username, password=password)
			if user is not None:
				login(request, user)
				# 若是登入成功,重定向要主頁
				return HttpResponseRedirect(reverse('index'))
            else:
            	# user爲None,說明帳號或密碼錯誤
                return render(request, "login.html", {"msg": "用戶名或密碼錯誤"})
        else:
        	# 表單無效,返回login_form對象便可,在template調用login_form.errors這個字典去獲取相關的錯誤
            return render(request, "login.html", {"login_form": login_form})
複製代碼

顯然,若是單純使用ModelBackend.authenticate的驗證邏輯是不能知足咱們的需求,咱們登陸的帳號能夠是username,也能夠是手機/郵箱等,這時候,咱們能夠進行一個自定義的登陸邏輯驗證。session

  1. 首先在view中寫本身的Backend,最好直接繼承ModelBackend
  2. 重載authenticate方法,參數直接來自auth.authenticate,但由於驗證須要用到表單中的username和password,因此前面提到,auth.authenticate也至少去接受這兩個關鍵參數
  3. 用Q方法能夠在進行或操做,若是用','是使用與操做,因爲數據庫中的password是加密的,不能直接使用password=password,django爲咱們提供了check_password方法進行驗證。
  4. 若是驗證經過須要返回user對象,不然返回None
  5. 在setting中配置
# app+views+backend名字
    AUTHENTICATION_BACKENDS = (  
        'users.views.MyUserBackend',  
    )
複製代碼
from django.db.models import Q
from django.contrib.auth.hashers import make_password

class MyUserBackend(ModelBackend):
    """ 自定義用戶驗證 """
    def authenticate(self, username=None, password=None, **kwargs):
        try:
            user = UserProfile.objects.get(Q(username=username) | Q(email=username) | Q(mobile=username))
            if user.check_password(password):
                return user
        except Exception as e:
            return None


複製代碼

django.contrib.auth.logout

順便說起一下logout函數,因爲django已經爲咱們提供好了退出的處理,使用起來十分簡單:app

class LogoutView(View):
    def get(self, request):
        logout(request)
        return HttpResponseRedirect(reverse('index'))
複製代碼

logout函數主要完成:函數

  1. 將request.session清除
  2. request.user = AnonymousUser()將用戶設置與匿名用戶
相關文章
相關標籤/搜索