我希望你能幫助我找出使用密碼實現手動(服務器端啓動)登錄而不使用的最佳方式。讓我來解釋的工作流程:手動登錄沒有密碼的用戶
- 用戶註冊
- 謝謝!與激活鏈接的電子郵件已經發送blablabla
- (賬戶現在存在,但被標記爲未啓用)
- 用戶打開郵件,點擊鏈接
- (帳戶啓用)
- 謝謝!您現在可以使用該網站
我想要做的是在用戶點擊郵件鏈接後登錄,以便他可以立即開始使用該網站。
我不能使用他的密碼,因爲它在數據庫中加密,是編寫自定義身份驗證後端的唯一選項嗎?
我希望你能幫助我找出使用密碼實現手動(服務器端啓動)登錄而不使用的最佳方式。讓我來解釋的工作流程:手動登錄沒有密碼的用戶
我想要做的是在用戶點擊郵件鏈接後登錄,以便他可以立即開始使用該網站。
我不能使用他的密碼,因爲它在數據庫中加密,是編寫自定義身份驗證後端的唯一選項嗎?
您不需要密碼即可登錄用戶。auth.login
function只需要一個User
對象,當您啓用該帳戶時,您大概已從數據庫獲取該對象。所以你可以直接通過login
。
當然,你需要是非常請注意,用戶無法欺騙到現有的已啓用帳戶的鏈接,然後該帳戶將自動以該用戶的身份登錄。
from django.contrib.auth import login
def activate_account(request, hash):
account = get_account_from_hash(hash)
if not account.is_active:
account.activate()
account.save()
user = account.user
login(request, user)
...等
編輯:
嗯,沒有注意到,規定使用authenticate
,因爲它增加了額外的屬性。查看代碼,它所做的只是一個backend
屬性,與驗證後端的模塊路徑相同。所以你可以僞造它 - 在上面的登錄電話之前,執行此操作:
user.backend = 'django.contrib.auth.backends.ModelBackend'
Daniel的答案非常好。
另一種方法是創建這樣的自定義授權後端https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#writing-an-authentication-backend這樣的HashModelBackend:
class HashModelBackend(object):
def authenticate(self, hash=None):
user = get_user_from_hash(hash)
return user
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
,然後在設置安裝此:
AUTHENTICATION_BACKENDS = (
'myproject.backends.HashModelBackend',
'django.contrib.auth.backends.ModelBackend',
)
那麼你的看法是像這樣:
def activate_account(request, hash):
user = authenticate(hash=hash)
if user:
# check if user is_active, and any other checks
login(request, user)
else:
return user_not_found_bad_hash_message
您可以使用ska
包,它具有實現無密碼登錄到Django。 ska
與認證令牌一起工作,其安全性基於SHARED_KEY,對於涉及的所有參與方(服務器)應該相同。
在客戶端(請求無密碼登錄的一方),您將生成一個URL並使用ska
對其進行簽名。示例:
from ska import sign_url
from ska.contrib.django.ska.settings import SECRET_KEY
server_ska_login_url = 'https://server-url.com/ska/login/'
signed_url = sign_url(
auth_user = 'test_ska_user_0',
secret_key = SECRET_KEY,
url = server_ska_login_url
extra = {
'email': '[email protected]',
'first_name': 'John',
'last_name': 'Doe',
}
)
標記的默認生存期爲600秒。您可以通過證明lifetime
參數來自定義該參數。
在服務器端(用戶登錄的站點),考慮到您已正確安裝ska
,用戶 在訪問URL(如果它們存在(用戶名匹配)或以其他方式創建時已登錄) 。您可以在項目的Django設置中自定義3個回調。
USER_GET_CALLBACK(string):如果成功從數據庫(現有用戶)獲取用戶,則觸發。 USER_CREATE_CALLBACK(字符串):在創建用戶(用戶不存在)後立即觸發。 USER_INFO_CALLBACK(string):成功驗證後觸發。
有關更多信息,請參閱文檔(http://pythonhosted.org/ska/)。
迴應和的回答。
寫你的後端道:
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
class HashModelBackend(ModelBackend):
def authenticate(self, username=None, **kwargs):
UserModel = get_user_model()
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
try:
user = UserModel._default_manager.get_by_natural_key(username)
return user
except UserModel.DoesNotExist:
return None
答案是基於django.contrib.auth.backends.ModelBackend源代碼。這是實際的Django的1.9
我寧願下面Django的默認位置的自定義後端:
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'yours.HashModelBackend',
]
因爲帳號激活不足可能比登錄本身。據https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#specifying-authentication-backends:
AUTHENTICATION_BACKENDS事項的順序,因此,如果同樣的用戶名和密碼在多個後端有效,Django會在第一次正面比賽停止處理。
注意 這段代碼甚至不正確的密碼驗證用戶。
這段代碼中有語法錯誤,所以不清楚應該發生什麼('hash'被定義但未被使用,'username'被使用但未被定義)。 – 2016-08-16 10:15:32
@ amichai-schreiber謝謝!我已經更正了答案 – 2016-08-17 12:59:27
從Django 1.10開始,過程已經簡化。
在所有版本的Django中,爲了讓用戶登錄,它們必須是authenticated by one of your app's backends(由AUTHENTICATION_BACKENDS
設置控制)。
如果你只是想強行登陸,你可以要求用戶通過從該列表中的第一個後端認證:
from django.conf import settings
from django.contrib.auth import login
# Django 1.10+
login(request, user, backend=settings.settings.AUTHENTICATION_BACKENDS[0])
# Django <1.10 - fake the authenticate() call
user.backend = settings.AUTHENTICATION_BACKENDS[0]
login(request, user)
感謝;文檔同意,但也有以下警告: 「首先調用authenticate() 當您手動登錄用戶時,必須在調用login()之前調用authenticate()。authenticate()在用戶身上設置一個屬性,說明哪個驗證後端成功驗證了該用戶(請參閱後端文檔以瞭解詳細信息),並且稍後在登錄過程中需要此信息。「 這可能是一個問題嗎? – Agos 2010-05-07 10:18:39
查看我的更新 – 2010-05-07 10:28:48
儘管從django.contrib.conf導入設置並分配settings.AUTHENTICATION_BACKENDS更好,以防使用自定義後端。 – Arsham 2014-09-24 14:29:25