我们如何修补 Django 以保持用户在会话之间登录
How we patched Django to keep users logged in between sessions
我们在使用 Django 的网站上遇到了问题。每次我们升级 Django 时,如果用户使用两个或多个不同的浏览器登录,然后他们从一个浏览器再次登录 - 他们会自动从所有其他会话(浏览器)注销。由于我们在去年将 Django 升级到新的主要版本大约 5 次,这让我们很头疼。我们不想强迫用户必须在会话之间一次又一次地登录。我们如何解决这个问题?
我们查了一下,这个问题是由于Django版本之间PBKDF2PasswordHasher.iterations
的变化引起的。每次我们将 Django 升级到新的主要版本(例如从 3.0 到 3.1)时,PBKDF2PasswordHasher.iterations
都会发生变化。这会导致用户下次登录时再次计算用户的散列密码,从而强制用户在所有其他会话中保持注销状态。我什至用 Django 的跟踪系统创建了一个 ticket。
有两种方法可以解决这个问题。首先,我们可以修补 class PBKDF2PasswordHasher
以保持 iterations
的数量不变,同时更新 def must_update
:
from django.contrib.auth.hashers import PBKDF2PasswordHasher
def patch():
def must_update(self, encoded):
# Update the stored password only if the iterations diff is at least 250,000.
algorithm, iterations, salt, hash = encoded.split('$', 3)
iterations_diff = abs(self.iterations - int(iterations))
return ((int(iterations) != self.iterations) and (iterations_diff >= 250000))
PBKDF2PasswordHasher.iterations = 180000 # Django 3.0.x
PBKDF2PasswordHasher.must_update = must_update
然后在我们基地AppConfig
class:
class SpeedyCoreBaseConfig(AppConfig):
name = 'speedy.core.base'
verbose_name = _("Speedy Core Base App")
label = 'base'
def ready(self):
locale_patches.patch() # Another patch
session_patches.patch() # This patch
或者,您可以从 PBKDF2PasswordHasher
继承新的 class,更改 iterations
和 def must_update
,并在设置中使用新的 class ( PASSWORD_HASHERS
)。我们使用了第一个选项,尽管从软件工程的角度来看使用第二个选项(继承一个新的 class)可能会更好。他们都工作。
我们在使用 Django 的网站上遇到了问题。每次我们升级 Django 时,如果用户使用两个或多个不同的浏览器登录,然后他们从一个浏览器再次登录 - 他们会自动从所有其他会话(浏览器)注销。由于我们在去年将 Django 升级到新的主要版本大约 5 次,这让我们很头疼。我们不想强迫用户必须在会话之间一次又一次地登录。我们如何解决这个问题?
我们查了一下,这个问题是由于Django版本之间PBKDF2PasswordHasher.iterations
的变化引起的。每次我们将 Django 升级到新的主要版本(例如从 3.0 到 3.1)时,PBKDF2PasswordHasher.iterations
都会发生变化。这会导致用户下次登录时再次计算用户的散列密码,从而强制用户在所有其他会话中保持注销状态。我什至用 Django 的跟踪系统创建了一个 ticket。
有两种方法可以解决这个问题。首先,我们可以修补 class PBKDF2PasswordHasher
以保持 iterations
的数量不变,同时更新 def must_update
:
from django.contrib.auth.hashers import PBKDF2PasswordHasher
def patch():
def must_update(self, encoded):
# Update the stored password only if the iterations diff is at least 250,000.
algorithm, iterations, salt, hash = encoded.split('$', 3)
iterations_diff = abs(self.iterations - int(iterations))
return ((int(iterations) != self.iterations) and (iterations_diff >= 250000))
PBKDF2PasswordHasher.iterations = 180000 # Django 3.0.x
PBKDF2PasswordHasher.must_update = must_update
然后在我们基地AppConfig
class:
class SpeedyCoreBaseConfig(AppConfig):
name = 'speedy.core.base'
verbose_name = _("Speedy Core Base App")
label = 'base'
def ready(self):
locale_patches.patch() # Another patch
session_patches.patch() # This patch
或者,您可以从 PBKDF2PasswordHasher
继承新的 class,更改 iterations
和 def must_update
,并在设置中使用新的 class ( PASSWORD_HASHERS
)。我们使用了第一个选项,尽管从软件工程的角度来看使用第二个选项(继承一个新的 class)可能会更好。他们都工作。