標籤:word 管理員 ike perm djang data- 實現 amp 要求
在Django中定製身分識別驗證
Django附帶的認證對於大多數常見情況來說已經足夠了,但您可能需要通過開箱即用的預設設定才能滿足需求。 要為您的項目定製身分識別驗證,需要瞭解提供的系統的哪些點可擴充或可替換。
身分識別驗證後端為使用者模型儲存的使用者名稱和密碼需要針對與Django預設不同的服務進行身分識別驗證時提供了一個可擴充的系統。 您可以給您的模型定製可以通過Django的授權系統進行檢查的許可權。 您可以擴充預設的使用者模型,或者替換完全自訂的模型。
其他驗證來源
您可能有時需要掛接到另一個身分識別驗證來源 - 也就是另一個使用者名稱和密碼來源或驗證方法。
例如,您的公司可能已經有一個LDAP設定,為每個員工儲存使用者名稱和密碼。如果使用者在LDAP和基於Django的應用程式中有單獨的帳戶,那麼對網路系統管理員和使用者本身來說都是一件麻煩事。
所以,為了處理這樣的情況,Django認證系統可以讓你插入其他認證源。您可以重寫Django的預設基於資料庫的方案,或者可以與其他系統一起使用預設系統。
指定認證後端
在幕後,Django維護一個驗證後端列表,它檢查身分識別驗證。當有人調用authenticate()時(正如前一節中介紹的有關登入使用者的內容),Django會嘗試在其所有身分識別驗證後端進行身分識別驗證。如果第一種認證方法失敗,
Django嘗試第二個,等等,直到所有的後端嘗試。
在AUTHENTICATION_BACKENDS設定中指定要使用的身分識別驗證後端列表。 這應該是一個Python路徑名列表,指向知道如何進行身分識別驗證的Python類。 這些類可以在你的Python路徑上的任何地方。 預設情況下,AUTHENTICATION_BACKENDS
被設定為:
[‘django.contrib.auth.backends.ModelBackend‘]
這是檢查Django使用者資料庫並查詢內建許可權的基本驗證後端。它不提供通過任何速率限制機制防止暴力密碼破解攻擊的保護。您可以在自訂授權後端中實現您自己的速率限制機制,也可以使用大多數Web伺服器提供的機制。 AUTHENTICATION_BACKENDS的順序很重要,所以如果相同的使用者名稱和密碼在多個後端有效,Django將在第一次正面匹配時停止處理。如果後端引發PermissionDenied異常,認證將立即失敗。 Django不會檢查後面的後端。
一旦使用者通過身分識別驗證,Django就會儲存哪些後端用於在使用者會話中對使用者進行身分識別驗證,並在需要訪問當前身分識別驗證的使用者時在該會話期間重新使用相同的後端。這實際上意味著每個會話都會緩衝身分識別驗證源,因此如果您更改AUTHENTICATION_BACKENDS,則需要清除會話資料(如果需要強制使用者使用不同方法重新進行身分識別驗證)。一個簡單的方法就是執行Session.objects.all().delete()
編寫身分識別驗證後端
認證後端是一個實現兩個必需方法的類:get_user(user_id)和authenticate(** credentials),以及一組可選的許可權相關授權方法。 get_user方法需要一個user_id - 可以是一個使用者名稱,資料庫ID或其他,但必須是你的使用者物件的主鍵 - 並返回一個使用者物件。 驗證方法將憑據作為關鍵字參數。 大多數情況下,它看起來像這樣:
class MyBackend(object): def authenticate(self, username=None, password=None): # Check the username/password and return a User. ...
但它也可以驗證令牌,如下所示:
class MyBackend(object): def authenticate(self, token=None): # Check the token and return a User. ...
無論哪種方式,身分識別驗證都應該檢查它擷取的憑據,並且如果認證有效,它應該返回與這些憑證相匹配的使用者物件。 如果它們無效,則應返回無。
Django管理系統與本章開頭描述的Django使用者物件緊密耦合。
現在,處理這個問題的最好方法是為每個存在於後端的使用者建立一個Django User對象(例如,在您的LDAP目錄,外部SQL資料庫等中)。您可以編寫指令碼來執行此操作 或者您的驗證方法可以在使用者首次登入時執行此操作。
以下是一個樣本後端,它會根據settings.py檔案中定義的使用者名稱和密碼變數進行身分識別驗證,並在使用者首次進行身分識別驗證時建立一個Django使用者物件:
from django.conf import settingsfrom django.contrib.auth.models import User, check_passwordclass SettingsBackend(object): """ Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD. Use the login name, and a hash of the password. For example: ADMIN_LOGIN = ‘admin‘ ADMIN_PASSWORD = ‘sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de‘ """ def authenticate(self, username=None, password=None): login_valid = (settings.ADMIN_LOGIN == username) pwd_valid = check_password(password, settings.ADMIN_PASSWORD) if login_valid and pwd_valid: try: user = User.objects.get(username=username) except User.DoesNotExist: # Create a new user. Note that we can set password # to anything, because it won‘t be checked; the password # from settings.py will. user = User(username=username, password=‘password‘) user.is_staff = True user.is_superuser = True user.save() return user return None def get_user(self, user_id): try: return User.objects.get(pk=user_id) except User.DoesNotExist: return None
處理自訂後端中的授權
自訂授權後端可以提供他們自己的許可權。 使用者模型會將許可權尋找函數(get_group_permissions(),get_all_permissions(),has_perm()和has_module_perms())委託給實現這些函數的任何驗證後端。 賦予使用者的許可權將是所有後端返回的所有許可權的超集。 也就是說,Django向任何一個後端授予的使用者授予許可權。
如果後端在has_perm()或has_module_perms()中引發PermissionDenied異常,授權將立即失敗,Django將不檢查後面的後端。 上面的簡單後端可以簡單地為管理員實現許可權:
class SettingsBackend(object): ... def has_perm(self, user_obj, perm, obj=None): if user_obj.username == settings.ADMIN_LOGIN: return True else: return False
這給上面例子中授予存取權限的使用者提供了完全的許可權。 請注意,除了給予相關使用者功能的相同參數之外,後端授權功能都將使用者物件(可能是匿名使用者)作為參數。
完整的授權實現可以在django / contrib / auth / backends.py中的ModelBackend類中找到,它是預設的後端,它大部分時間都會查詢auth_permission表。 如果您希望僅為後端API的一部分提供自訂行為,則可以利用Python繼承和子類ModelBackend,而不是在自訂後端中實現完整的API。
匿名使用者授權
匿名使用者是未經過身分識別驗證的使用者,即他們未提供有效身分識別驗證詳細資料。 但是,這並不一定意味著他們無權做任何事情。 在最基本的層面上,大多數網站授權匿名使用者瀏覽大部分網站,並且許多網站允許匿名發布評論等。
Django的許可權架構沒有地方為匿名使用者儲存許可權。 但是,傳遞給身分識別驗證後端的使用者物件可能是django.contrib.auth.models.AnonymousUser對象,允許後端為匿名使用者指定自訂授權行為。
這對於可重用應用程式的作者特別有用,他們可以將授權的所有問題委託給auth後端,而不需要設定,例如控制匿名訪問。
對非活躍使用者授權
非活躍使用者是經過身分識別驗證的使用者,但其屬性is_active設定為False。 但是,這並不意味著他們無權做任何事情。 例如,他們被允許啟用他們的帳戶。
對許可權系統中的匿名使用者的支援允許匿名使用者有權執行某些操作,而不活動的經過身分識別驗證的使用者則不能這樣做。 不要忘記在你自己的後端許可權方法中測試使用者的is_active屬性。
處理對象許可權
Django的許可權架構為對象許可權奠定了基礎,但核心中沒有實現它。 這意味著檢查對象許可權將始終返回False或一個空列表(取決於執行的檢查)。 身分識別驗證後端將為每個對象相關的授權方法接收關鍵字參數obj和user_obj,並可以根據需要返回對象層級許可權。
自訂許可權
要為給定的模型對象建立自訂許可權,請使用許可權模型元屬性。 本樣本任務模型建立三個自訂許可權,即使用者可以使用或不能使用Task執行個體執行的操作,具體針對您的應用程式:
class Task(models.Model): ... class Meta: permissions = ( ("view_task", "Can see available tasks"), ("change_task_status", "Can change the status of tasks"), ("close_task", "Can remove a task by setting its status as closed"), )
這樣做的唯一方法是在運行manage.py遷移時建立這些額外的許可權。 當使用者試圖訪問應用程式提供的功能(查看任務,更改任務狀態,關閉任務)時,您的代碼負責檢查這些許可權的值。繼續上面的樣本,以下樣本將檢查使用者 可能會查看任務:
user.has_perm(‘app.view_task‘)
擴充現有的使用者模型
有兩種方法可以擴充預設使用者模型,而不用替換自己的模型。 如果您需要的更改是純粹的行為,並且不需要對儲存在資料庫中的內容進行任何更改,則可以基於使用者建立代理模型。 這允許代理模型提供的任何功能,包括預設排序,自訂管理器或自訂模型方法。
如果您希望儲存與使用者相關的資訊,則可以使用包含欄位的模型的一對一關聯性以擷取更多資訊。 這種一對一模式通常稱為設定檔模型,因為它可能儲存有關網站使用者的非auth相關資訊。 例如,您可以建立一個Employee模型:
from django.contrib.auth.models import Userclass Employee(models.Model): user = models.OneToOneField(User) department = models.CharField(max_length=100)
假設現有員工Fred Smith擁有User和Employee模型,則可以使用Django的標準相關模型約定訪問相關資訊:
>>> u = User.objects.get(username=‘fsmith‘)>>> freds_department = u.employee.department
要將設定檔模型的欄位添加到admin的使用者頁面,請在應用程式的admin.py中定義InlineModelAdmin(對於本樣本,我們將使用StackedInline),並將其添加到UserAdmin類,該類用User類註冊:
from django.contrib import adminfrom django.contrib.auth.admin import UserAdminfrom django.contrib.auth.models import Userfrom my_user_profile_app.models import Employee# Define an inline admin descriptor for Employee model# which acts a bit like a singletonclass EmployeeInline(admin.StackedInline): model = Employee can_delete = False verbose_name_plural = ‘employee‘# Define a new User adminclass UserAdmin(UserAdmin): inlines = (EmployeeInline, )# Re-register UserAdminadmin.site.unregister(User)admin.site.register(User, UserAdmin)
這些設定檔模型在任何方面都不是特別的 - 它們只是恰好與使用者模型具有一對一連結的Django模型。因此,建立使用者時不會自動建立,但可以根據需要使用django.db.models.signals.post_save建立或更新相關模型。
請注意,使用相關模型會產生額外的查詢或串連以檢索相關資料,根據您的需要,替換使用者模型並添加相關欄位可能是更好的選擇。但是,項目應用程式中預設使用者模型的現有連結可能會導致額外的資料庫負載。
代替自訂使用者模型
某些類型的項目可能具有身分識別驗證要求,因此Django的內建User模型並不總是適合的。例如,在一些網站上,使用電子郵件地址作為您的身份標記而不是使用者名稱更有意義。 Django允許您通過為引用自訂模型的AUTH_USER_MODEL設定提供值來覆蓋預設的使用者模型:
`AUTH_USER_MODEL = ‘books.MyUser‘`
此虛線對描述了Django應用程式的名稱(它必須位於INSTALLED_APPS中),以及您希望用作使用者模型的Django模型的名稱。
改變AUTH_USER_MODEL對你的Django項目有很大的影響,特別是你的資料庫結構。 例如,如果在運行遷移後更改AUTH_USER_MODEL,則必須手動更新資料庫,因為它會影響許多資料庫表關係的構建。 除非有充分理由這樣做,否則不應更改AUTH_USER_MODEL。
儘管有上述警告,但Django完全支援自訂使用者模型,但完整的解釋超出了本書的範圍。 Django專案網站上提供了一個完全符合管理員要求的自訂使用者應用程式樣本,以及有關自訂使用者模型的全面文檔。
轉載自:https://www.jianshu.com/p/5806ff9c0cc5
在Django中定製身分識別驗證