iT邦幫忙

0

Django User is_active 的判斷

各位先進大家好,最近在學習Django version 3.2,日前依書練習中碰到一個讓我無法理解的狀況,經由Django admin後台建立User,設定密碼後,可以正常登入Web,不過一旦將該User的is_active uncheck後,登入便失敗,而非是Disabled User的訊息;經查authenticate()的結果是None,所以沒有User Object,因此無法檢查is_active,無法進入not None檢查邏輯中。
想請教要如何才能讓Disabled User在輸入正確的credentials後,authenticate()可如同Enabled User一樣,傳回not None的結果。接著再檢查User.is_active狀態做不同的處理。謝謝!!

1 個回答

0
froce
iT邦大師 1 級 ‧ 2021-06-10 16:21:22

User物件有check_password(raw_password)和set_password(raw_password)
https://docs.djangoproject.com/en/3.2/ref/contrib/auth/

大概的用法

from django.contrib.auth.models import User
user = User.objects.filter(username=user_input_account)
if user.is_active is False and user.check_password(user_input_password):
    ....whatever You want to do

authenticate()是為了抽象化backend所建立的接口,跟你要的用法不太一樣。
看得懂的話建議可以自己去客製 authentication backend。
https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#authentication-backends

看更多先前的回應...收起先前的回應...

謝謝!!你的做法是跳過authenticate()的做法,先取得User Object,不過我的問題是Disabled User經authenticate()檢查,登入失敗,如何讓系統的回復訊息是『你的帳號已停用,請洽系統管理員』等等之類的,而非如同帳密錯誤的User一樣是『帳密錯誤』的訊息。

froce iT邦大師 1 級 ‧ 2021-06-11 08:08:31 檢舉

authenticate()是為了抽象化backend所建立的接口,目的是為了依照需求客製化auth backend,所以他的預設行為應該是固定的,檢查完認證對不對後,照django的方式放行。
你不該去想改預設(django.contrib.auth.backends.ModelBackend)authenticate()的行為,反而應該是在authenticate()前先檢查,所以我才跟你說先去查如何利用客製backend改authenticate()或直接用User物件怎麼做這件事...

另外 Django 有幫你先寫好其他的backend,請看這裡: https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#authorization-for-inactive-users
但我不知道有沒有符合你的要求。

基本上不是改backend就是直接先檢查User。

謝謝!!我想下列的敘述:
The get_user method takes a user_id – which could be a username, database ID or whatever, but has to be the primary key of your user object – and returns a user object or None.
應該是我要執行的function,先確認在disabled狀態下,該User ID能否取得User object後,再決定是否要做authenticate()。因為我的測試狀況是User ID/PWD都沒異動的情況下,變更active狀態下,得到非預期的結果。

用你說的user=User.objects.filter(username=user_input_account)的方式,結果if user is not None: print("user is existing) 嘗試print user.first_name, user.is_active都得到下列訊息
Exception Value:
'QuerySet' object has no attribute 'first_name'
看來這條檢驗方式是不行的。

好消息,改用User.objects.get(username=username)就可以取得User Object接著就可以先驗證is_active,False告知User Disabled,True再驗證authenticate()就可以了。

froce iT邦大師 1 級 ‧ 2021-06-15 09:55:42 檢舉

好消息,改用User.objects.get(username=username)就可以取得User Object接著就可以先驗證is_active,False告知User Disabled,True再驗證authenticate()就可以了。

我怎麼可能知道你的欄位存在哪個變數...
user = User.objects.filter(username=user_input_account)
這句就是在告訴你去檢查使用者帳號欄位有沒有這個user。

The get_user method takes a user_id – which could be a username, database ID or whatever, but has to be the primary key of your user object – and returns a user object or None.

這句就是我一直在告訴你的兩個方法,另外 AllowAllUsersModelBackend 會略過 is_active 的檢查,在authenticate()不管是不是停用,直接回傳user(基本上就是改寫backend),這個應該比較接近你的描述。

我要發表回答

立即登入回答