1. 程式人生 > 其它 >Django | 使用者認證:Auth模組具體使用

Django | 使用者認證:Auth模組具體使用

Auth模組

  • 什麼是auth模組?
Auth模組是Django自帶的使用者認證模組:
	我們在開發一個網站的時候,無可避免的需要設計實現網站的使用者系統。此時我們需要實現包括使用者註冊、使用者登入、使用者認證、登出、修改密碼等功能,這些功能幾乎是所有軟體都需要開發的功能,那麼我們之前在寫這些功能的時候也是需要花費一些時間書寫程式碼邏輯的,那麼Django自帶的auth模組就會很輕鬆的幫助我們完成這些功能,它預設使用 auth_user 表來儲存使用者資料。
  • auth_user表
# 其實我們很早就應該見過這張表只是把它忽略了。
	- 其實我們在建立好一個django專案之後直接執行資料庫遷移命令會自動生成很多表,那麼其中一張表就是auth_user表

# 基本用處:
    - django在啟動之後就可以直接訪問admin路由,需要輸入使用者名稱和密碼,資料參考的就是auth_user表,並且還必須是管理員使用者才能進入
    
# 怎麼建立超級使用者(管理員)
	- 首先要資料庫遷移
        makemigrations
        migrate
    - 建立超級使用者命令:	
        python3 manage.py createsuperuser

接下來就使用auth_user表來實現使用者的登入,註冊,登出...功能:

登入功能:

# 校驗使用者民或密碼是否一致
# 關鍵字:auth.authenticate(username=使用者輸入的使用者名稱,password=使用者輸入的密碼)
# 需匯入模組:
from django.contrib import auth


def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 那麼現在如何校驗資料呢?
            # 獲取表的資料 但是密碼是密文的怎麼比對呢
        # 這時就要用到auth模組
        res = auth.authenticate(request,username=username,password=password)
        '''
            他都幹了那些事:
                自動查詢auth_user表
                自動給密碼加密後再進行比對
            注意事項:
                括號內必須同時傳入使用者名稱和密碼
                不能只傳使用者名稱
        '''
        print(res,type(res))
        print(res.username)
        print(res.password)
    return render(request,'login.html')

儲存使用者登陸狀態

# 關鍵字:auth_login(request,使用者物件)
# 方法優點:只要執行了auth.login方法,就可以在任何地方通過request.user獲取到當前登入的使用者物件



def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        user_obj = auth.authenticate(request,username=username,password=password)
        if user_obj:
            # 之前我們儲存使用者登入狀態是不是要通過session來儲存。現在可通過auth來直接幫助我們操作session表
            # 儲存使用者登入狀態:
            auth.login(request,user_obj)  # 類似於request_session[key] = user_obj
            return redirect('/home/')   # 跳轉到home頁面


    return render(request,'login.html')

def home(request):
    print(request.user)   # 可以拿到當前登入的使用者物件
    return HttpResponse('home')

判斷使用者是否登入

# 如上:那麼如果沒有登入,直接訪問home頁面,requeest.user返回的是什麼呢?
# 結果:如果沒有登入則返回的是AnonymousUser匿名使用者

# 那麼如果判斷使用者是否登入了呢?
# 關鍵字:request.user.is_authenticated
# 返回結果:布林型別:
        - 未登入(匿名使用者)	 :返回False
        - 已登入			:返回True

校驗是否登入裝飾器

# 上述看到我們匿名使用者也可以登入到home頁面,這樣是不合理的,需要登陸後才能訪問其他頁面才合理。那麼就需要校驗使用者是否登入

# 需匯入模組:
    - from django.contrib.auth.decorators import login_required
# 關鍵字:新增裝飾器
    - 區域性配置:@login_required(login_url='/指定未登入跳轉頁面/')
    - 全域性配置:@login_required   # 無需指定跳轉路徑
    	# 需要在settings.py配置檔案中配置:LOGIN_URL = '/指定未登入跳轉頁面/'
區域性和全域性哪個好呢?
    全域性的好處在於無需重複寫程式碼 但是跳轉的頁面卻很單一
    區域性的好處在於不同的檢視函式在使用者沒有登陸的情況下可以跳轉到不同的頁面

修改密碼

# 修改密碼:
    - 需要校驗舊密碼是否正確
    - 需要將新密碼從auth_user表中修改並儲存
<form action="" method="post">
    {% csrf_token %}
    <p>username<input type="text" name="username" disabled value="{{ request.user.username }}"></p>
    <p>old_password:<input type="text" name="old_password"></p>
    <p>new_password:<input type="text" name="new_password"></p>
    <p>confirm_password:<input type="text" name="confirm_password"></p>
    <input type="submit">
    
</form>
# 校驗舊密碼:
# 關鍵字:request.user.check_password('需要校驗的資料(舊密碼)')
     	- 相當於:將當前表的password欄位和使用者輸入的舊密碼進行比對
    
# 修改密碼並同步到資料庫:
# 關鍵字:request.user.set_password(此處放新密碼)
@login_required
def set_password(request):
    if request.method == 'POST':
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        confirm_password = request.POST.get('confirm_password')
        # 校驗兩次密碼是否一直
        if new_password == confirm_password:
            # 校驗老密碼:
            is_right =  request.user.check_password(old_password)   # 返回的是布林值
            if is_right:
                # 修改密碼
                request.user.set_password(new_password)  # 修改物件的屬性
                request.user.save()   # 同步到資料庫
        return redirect('/login/')   # 註冊完之後跳轉到登入頁面
    return render(request,'setpassword.html',locals())

登出功能

# 登出則是將session表中的使用者資料刪除即可。
# 關鍵字:auth.logout(request)


@login_required   # 登入才能登出所以也需要驗證是否登入。
def logout(request):
    auth.logout(request)
    return redirect('/login/')

註冊功能

# 原理:操作auth_user表寫入資料:
# 關鍵字:User.objects.create(username=username,password=password)

# 需匯入模組:
from django.contrib.auth.models import User

def register(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 操作auth_user表寫入資料
        User.objects.create(username=username,password=password)

    return render(request,'register.html')
# 綜上:寫入資料 不能用create 密碼沒有加密 處理

# 建立普通使用者
User.objects.create_user(username=username,password=password)
# 建立超級使用者(瞭解):使用程式碼建立超級使用者 郵箱是必填的 而用命令建立則可以不填
User.objects.create_superuser(username=username,email='[email protected]',password=password)

總結:

# 1.比對使用者名稱和密碼是否正確
user_obj = auth.authenticate(request,username=username,password=password)
# 括號內必須同時傳入使用者名稱和密碼
print(user_obj)  # 返回使用者物件   資料不符合則返回None
print(user_obj.username)  # 使用者名稱
print(user_obj.password)  # 密文

# 2.儲存使用者狀態
auth.login(request,user_obj)  # 類似於request.session[key] = user_obj
# 只要執行了該方法 你就可以在任何地方通過request.user獲取到當前登陸的使用者物件

# 3.判斷當前使用者是否登陸
request.user.is_authenticated()

# 4.獲取當前登陸使用者物件
request.user

# 5.校驗使用者是否登陸裝飾器
from django.contrib.auth.decorators import login_required
# 區域性配置
@login_required(login_url='/login/') 
# 全域性配置
LOGIN_URL = '/login/'
	1.如果區域性和全域性都有 該聽誰的?
    區域性 > 全域性
	2.區域性和全域性哪個好呢?
    全域性的好處在於無需重複寫程式碼 但是跳轉的頁面卻很單一
    區域性的好處在於不同的檢視函式在使用者沒有登陸的情況下可以跳轉到不同的頁面

# 6.比對原密碼
request.user.check_password(old_password)

# 7.修改密碼
request.user.set_password(new_password)  # 僅僅是在修改物件的屬性
request.user.save()  # 這一步才是真正的操作資料庫

# 8.登出
auth.logout(request) 

# 9.註冊
# 操作auth_user表寫入資料
User.objects.create(username=username,password=password)  # 寫入資料  不能用create 密碼沒有加密處理
# 建立普通使用者
User.objects.create_user(username=username,password=password)
# 建立超級使用者(瞭解):使用程式碼建立超級使用者 郵箱是必填的 而用命令建立則可以不填
User.objects.create_superuser(username=username,email='[email protected]',password=password)

如何擴充套件auth_user表

# 比如給auth_user表新增一個phone欄位,那麼該如何擴建呢?

from django.contrib.auth.models import User   # auth_user所在的表位置

我們先來看一下這張表都有那些欄位:
# 所以我們在擴充套件auth_user表是隻需要繼承AbstractUser即可
# 舉例:
# 需匯入模組:
from django.contrib.auth.models import User,AbstractUser

class UserInfo(AbstractUser):
    phone = models.BigIntegerField()

# 需要注意:
	如果繼承了AbstractUser
    那麼在執行資料庫遷移命令的時候auth_user表就不會再創建出來了
    而UserInfo表中會出現auth_user所有的欄位外加自己擴充套件的欄位
    這麼做的好處在於我們能夠直接點選我們自己的表更加快捷的完成操作以及擴充套件
    
    - 前提:
    	1、在繼承之前沒有執行過資料庫遷移的命令
        	即auth_user表沒有被創建出來,如果當前庫已經建立了那麼就需要重新建立一個庫
        2、繼承的類裡面不要覆蓋AbstractUser裡面的欄位名
        	表裡面有的欄位不要動,只擴充套件額外的欄位即可
        3、需要再配置檔案中告訴django你要用UserInfo代替auth_user
        	AUTH_USER_MODEL = 'app01.UserInfo'   # 應用名.表名
            
如果自己寫表替代了auth_user那麼
auth模組的功能還是照常使用,參考的表由原來的auth_user變成了UserInfo
# 比如:
	- 原先:
        from django.contrib.auth.models import User
        User.objects.create(username=username,password=password)
        
    - 現在:
        from app01 import models
        models.UserInfo.objects.create(username=username,password=password)
        
# 方法不變只是操作的表換成了自己指定的表。