python-Django基本流程原理02-認證系統

yiyumo發表於2020-10-14

一. Django預設使用者認證系統

Django 認證提供了實現認證(authentiaction)和授權(authorization)兩種功能的使用者認證系統–auth 使用的儲存表auth_user
參考文件點這裡

Django使用者認證系統它處理使用者賬號、組、許可權以及基於cookie的使用者會話。

  • Django認證系統同時處理認證和授權:
    • 認證:驗證一個使用者是否可用於賬號登入。
    • 授權:授權決定一個通過了認證的使用者被允許做什麼。
  • Django認證系統包含的內容:
    • 使用者:使用者模型類、使用者認證。
    • 許可權:標識一個使用者是否可以做一個特定的任務。
    • 組:對多個具有相同許可權的使用者進行統一管理。
    • 密碼:一個可配置的密碼雜湊系統,設定密碼、密碼校驗。

主要模組:

from django.contrib import auth  //包含身份驗證框架的核心及其預設模型
from django.contrib import contenttypes      //是Django內容型別系統,它允許許可權與你建立的模型關聯。

模組詳解:

from django.contrib import auth //確保你的每個 Django 模型被建立時有四個預設許可權:新增、修改、刪除和檢視
from django.contrib.auth.models import User //user物件
from django.contrib.auth import authenticate  // authenticate驗證使用者
from django.contrib.auth.models import Group //對使用者進行分類的通用方法

user物件的許可權操作:
django.contrib.auth.models.User” 物件有兩個多對多欄位:groupsuser_permissions
可以通過 user_permissions 屬性將許可權分配給user,或通過 permissions 屬性分配給group

操作:

myuser.groups.set([group_list])
myuser.groups.add(group, group, ...)
myuser.groups.remove(group, group, ...)
myuser.groups.clear()
myuser.user_permissions.set([permission_list])
myuser.user_permissions.add(permission, permission, ...)
myuser.user_permissions.remove(permission, permission, ...)
myuser.user_permissions.clear()


我們看一下基本如何使用

二. 使用者認證系統實現例項

主要用到的幾個方法:

  • create_user 建立使用者
  • authenticate 驗證登入
  • login 記住使用者的登入狀態
  • logout 退出登入
  • is_authenticated 判斷使用者是否登入
  • login_required 判斷使用者是否登入的裝飾器

1. 建立使用者:

User 物件的主要屬性有 username, password, email, first_name, last_name

1.1 普通的建立使用者

from django.contrib.auth.models import User
user = User.objects.create_user('yym', 'yym@yiyumo.com', 'yympassword')

~ 建立超級使用者指令 python manage.py createsuperuser –username=yym --email=yym@yym.com ~

1.2 更改密碼

    from django.contrib.auth.models import User
    u = User.objects.get(username='yym')
    u.set_password('new password')
    u.save()

~ 更改密碼指令 python manage.py changepassword username ~

2. 驗證使用者

使用 authenticate()來驗證使用者。它使用 usernamepassword 作為引數來驗證,對每個身份驗證後端進行檢查。如果後端驗證有效,則返回一個User 物件。如果後端引發 PermissionDenied錯誤,將返回 None

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    # A backend authenticated the credentials
else:
    # No backend authenticated the credentials

3. 許可權

當 INSTALLED_APPS 設定了 django.contrib.auth 時,它將確保你的每個 Django 模型被建立時有四個預設許可權:新增、修改、刪除和檢視

3.1 建立許可權

from car.models import UseCar
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

# 為車輛模型建立可釋出接單的許可權
content_type = ContentType.objects.get_for_model(UseCar)
permission = Permission.objects.create(
    codename='can_publish',
    name='Can Publish Posts',
    content_type=content_type,
)

3.2 許可權快取

第一次需要獲取使用者物件的許可權檢查時,ModelBackend才會快取它們的許可權

from django.contrib.auth.models import Permission, User
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404

from car.models import UseCar

def user_gains_perms(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    # any permission check will cache the current set of permissions
    user.has_perm('car.change_usecar')

    content_type = ContentType.objects.get_for_model(UseCar)
    permission = Permission.objects.get(
        codename='change_usecar',
        content_type=content_type,
    )
    user.user_permissions.add(permission)

    # Checking the cached permission set
    user.has_perm('car.change_usecar')  # False

    # Request new instance of User
    # Be aware that user.refresh_from_db() won't clear the cache.
    user = get_object_or_404(User, pk=user_id)

    # Permission cache is repopulated from the database
    user.has_perm('car.change_usecar')  # True

    ...

4. Web 請求的認證

4.1 web請求的驗證

Django 使用 sessions 和中介軟體將身份驗證系統掛接到請求物件中
它們在每次請求中都會提供 request.user 屬性。如果當前沒有使用者登入,這個屬性將會被設定為 AnonymousUser,否則將會被設定為 User例項。
使用 user 的屬性is_authenticated來區分 使用者是否已通過身份驗證
使用 user 的屬性is_anonymous來區分User和AnonymousUser 物件

if request.user.is_authenticated:
    user
    ...
else:
    pass

4.2 使用者的登入

將已驗證的使用者想附加到當前會話(session)中將通過 login() 函式完成

from django.contrib.auth import authenticate, login
def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(request, username=username, password=password) //驗證
    if user is not None:
        login(request, user)  //登入
        # Redirect to a success page.
        ...
    else:
        # Return an 'invalid login' error message.
        ...

4.3 使用者的登出

將已驗證的使用者想從當前會話(session)中將刪除通過 logout() 函式完成

from django.contrib.auth import logout

def logout_view(request):
    logout(request)

實際專案開發中常會遇到以下幾個問題(關於這些問題之後會詳細討論):

  1. 由於預設的user通常在實際開發中並不能滿足我們的需求,我們通常會繼承User表進行擴充以及擴充之後使用者建立時需注意密碼明文等問題。
  1. 現實中 由於session的一些缺點所以一般專案中會採用基於token的鑑權機制。
    1. 伺服器來說,必須儲存所有線上使用者的session,那麼這就佔用了很大的資源(cpu,記憶體),嚴重影響伺服器的效能.
    2. 擴充套件伺服器做叢集,但是同時也出現了分散式session的問題
  1. django 自帶的許可權機制無法滿足專案需求 會擴充許可權設定

session機制原理圖:

python-Django基本流程原理02-認證系統

token機制原理圖:

python-Django基本流程原理02-認證系統

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章