Django學習之九: auth 認證組件

Django auth 認證組件

Django提供的auth認證組件,提供了: 用戶表的構建方式(用於知足符合auth組件);提供了認證接口;提供了會話登陸和會話註銷的接口 ;提供了中間件將會話登陸用戶保存到request對對象中,這樣能夠很輕易的拿到登陸用戶,不用咱們再從會話中獲取用戶id,再經過model獲取到用戶對象;對於認證接口要提供用戶名和密碼傳入auth.authenticate(username,password),認證成功,就能夠獲得認證用戶對象。咱們只須要根據認證結果是否有對象,來斷定認證結果,來進行後面的操做。同時返回的用戶對象傳入auth.login(request, user)接口,調用接口,能夠將用戶登陸信息記錄到session中,而且若是添加了auth的一箇中間件AuthenticationMiddleware,那麼每次請求會在request.user中保存該登陸的用戶對象。若是沒登錄request.user會保存一個anonymouseuser用戶,這樣就能夠經過request.user的API來斷定本次請求是不是某個用戶登陸狀態。這點是auth組件關鍵點,這也是涉及到隱含session記錄建立和auth中間件對request對象的操做。前端

配置使用auth組件及其中間件

  1. 將auth app註冊到installed_apps列表中。即將‘django.contrib.auth’添加到列表中。
  2. 將contenttypes app註冊到installed_apps列表中。即將‘django.contrib.contenttypes’添加到列表中。這是django的 content type system, 有關權限的。
  3. 確保兩個中間件添加到配置文件MIDDLEWARE列表中:
    1. 'django.contrib.sessions.middleware.SessionMiddleware'
    2. 'django.contrib.auth.middleware.AuthenticationMiddleware'
  4. 設置auth組件使用的認證用戶表即Model。默認會使用auth模塊的 auth.User這個model.這個設置參數是AUTH_USER_MODEL='appname.UserModel' 這個值是app名字和模塊名,中間使用點鏈接,不用指定模塊名。這點要注意。
  5. 注意自定義的認證model類,這個model類必須繼承django.contrib.auth.models.AbstractUser類。該類提供了用戶名和密碼還有郵箱等字段。只須要自定義一些本身的字段就能夠了。主要提供了:
    1. username
    2. password
    3. email
    4. first_name
    5. last_name
  6. 定義本身的認證model類,實例:
from django.contrib.auth.models import AbstractUser
from django.db import models


class Users(AbstractUser):
    age = models.IntegerField(verbose_name='年齡', blank=True, null=True)
    telephone = models.CharField(verbose_name='手機號', max_length=32)
    address = models.CharField(verbose_name='住址', max_length=255)
    
    def __str__(self):
        return self.username  # username屬性繼承自AbstractUser
  1. settings文件中對應的AUTH_USER_MODEL = 'appname.Users' ,appname就是model所在的app名稱了。
  2. 最後一個和是否已認證登陸校驗相關的配置:LOGIN_URL 該設置定義了登陸url。用於auth組件提供的@login_required 裝飾器,裝飾器用於裝飾view視圖函數,當視圖函數須要校驗用戶登陸才能訪問時,

request.user 能夠直接在template模版中使用

方便在模版系統中渲染登陸用戶的信息。前提是使用auth組件進行會話登陸及其中間件。python

auth組件經常使用api

  1. auth.authenticate(username= login_name, password = pwd) 認證成功返回User對象,失敗返回None.
  2. auth.login(request, user) # 注意request是必須的,是請求對象,user是經過authenticate認證後獲得的。做用會話登陸,將登陸信息保存到會話中。若是當前會話已經產生會flush。
  3. request.user # 這個就是一個django.utils.functional.SimpleLazyObject對象,若是authenticate認證成功,返回的對象是model-user對象,也就是auth_user表對象;將該對象進過auth.login後,那麼request.user就是相應的該用戶;否則就是一個anonymous用戶。經過request.user能夠斷定是否有用戶登陸。重要:request.user是一個全局變量,能夠在視圖和模版中使用。
  4. auth.logout(request) 登出當前session中登陸的用戶,若是沒有用戶登陸,也不會報錯。登出後request.user就是annoymouse用戶了。會清空會話。
  5. reques.user.username能夠斷定是否有用戶登陸。不能使用request.user斷定是否有用戶登陸,由於沒有用戶登陸,這個也會返回一個annoymouse用戶,只有訪問其屬性纔會返回一些False值。因此經過request.user.* 的屬性才能斷定是否有用戶登陸的狀態。
  6. request.user.is_authenticated 斷定是否登陸返回True或False.
  7. django.contrib.auth.get_user_model() 能夠獲取到當前auth組件使用的認證model類。

注意區別兩個API斷定 ‘是否定證’ 與 ‘是否定證成功的區別’

即 auth.authenticate() 與 request.user.is_authenticated 的使用場景和功能區別:ajax

  • 二者看上去都是認證有關係,但兩種使用場景和目的是不一樣的。
  • 前者 是 認證 ,其返回的結果是User_obj 或者 None,目的是斷定認證是否成功,僅僅使用在登陸認證view視圖函數中。
  • 後者 是 是否有用戶登陸, 其返回結果是True 或者False。目的是校驗用戶是否登陸了,用於除了登陸認證view與不校驗用戶登陸的view。即須要校驗用戶登陸情況纔有後續操做的情景中。這個的前提是auth.authenticate和auth.login 兩個登陸過程操做。只有二者操做了,纔有登陸的斷定。

獲取認證model類

  1. 經過django.contrib.auth.get_user_model()
  2. 若是要在其它model類關聯使用的認證model類,最好經過django.conf.settings.AUTH_USER_MODEL獲取。這是最佳實踐,關聯認證model類。由於若是直接引用,萬一改變了model認證類的化,還要來改變這裏的代碼。
  3. 以上兩種方式是能夠互換的。

認證檢測裝飾器@login_required

導入語句: from django.contrib.auth.decorators import login_required
用法:用於裝飾須要視圖函數;使用了該裝飾器的函數,會斷定是否已登陸用戶,若是沒有將重定向到settings.LOGIN_URL指定的url並帶上一個next參數,next參數傳入當前視圖訪問的絕對路徑,已用於在登陸後跳轉的路徑。這樣,login視圖在登陸成功後的跳轉,就能夠從next提交的值獲取,並設置一個獲取不到的默認值爲'index'首頁就能夠了。很方便的裝飾器和其修改的next參數,其中next可用於模版中。
用法:django

@login_required
def list_customer(request):
    """
    查看用戶列表
    :param request:
    :return:
    """
    pass
    return HttpResponse('用戶列表')

auth模塊大大前提是,使用django的user model做爲用戶存儲

若是要自定義,能夠繼承AbstractUser這個抽象model。這就涉及到了model的繼承。抽象繼承屬於model繼承的table_per_class模式。api

user model提供了建立user object 的接口create_user();修改密碼的接口user.set_password()。這個操做普通model直接操做create,update數據不一樣,必須經過接口,由於密碼是加密存儲的。session

利用auth組件的登陸視圖函數:

# 登陸驗證頁面
def login(request):
    if request.method == 'POST':
        response = {
            'user': None,
            'msg': None,
        }
        login_name = request.POST.get('username')  # 由於使用的是ajax提交表單數據,對於表單數據的校驗就放到前端吧.
        pwd = request.POST.get('password')
        valid_code = request.POST.get('valid_code')
        if valid_code.upper() == request.session['valid_code'].upper():  # 只作驗證碼校驗和用戶認證校驗。
            user = auth.authenticate(username=login_name, password=pwd)
            if user:
                auth.login(request, user)  # 這樣request.user 就會有當前登陸對象
                response['user'] = user.username
                return JsonResponse(response)
            else:
                response['msg'] = '用戶名或密碼錯誤!'
                return JsonResponse(response)
        else:
            response['msg'] = '驗證碼錯誤!'
            return JsonResponse(response)
    return render(request, 'myblog/login.html')

小結

  1. 感受使用auth組件後,auth組件的耦合度過高了,很差擴展了。雖然提供的一些認證,登陸會話等比較好用,可是想本身擴展就比較難。因此仍是少用auth組件,使用本身的認證吧,能夠利用auth提供的一些工具API, 到咱們本身的認證代碼中。如:密碼的hash。
相關文章
相關標籤/搜索