如何根据 django 中以前使用的密码检查密码
How to check password against previously used passwords in django
我有以下模型用于存储以前使用的散列密码:
class PasswordHistory(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
password = models.CharField(max_length=128, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now = True)
在更改密码表单中,我想检查用户要更改的新密码是否在过去 5 次没有被使用过。
这是我的表单验证:
class ProfileForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput(), required=False)
password2 = forms.CharField(widget=forms.PasswordInput(), required=False)
class Meta:
model = Employee
user_id = None
def __init__(self, *args, **kwargs):
self.user_id = kwargs.pop('user_id', None)
super(ProfileForm, self).__init__(*args, **kwargs)
def clean_password2(self):
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 != password2:
raise forms.ValidationError('Passwords do not match.')
user = User.objects.get(pk=self.user_id)
hashed_password = make_password(password1)
password_histories = PasswordHistory.objects.filter(
user=user,
password_hashed_password
)
if password_histories.exists():
raise forms.ValidationError('That password has already been used')
return password2
问题是密码每次都不一样,即使我一遍又一遍地尝试使用相同的明文密码。因此:
if password_histories.exists():
永远不会 returns 正确。
如果过去的密码由于加盐而总是不同,我如何比较过去的密码?
谢谢
.set_password
函数确实没有 return 任何东西,它只是 设置 密码。但是就像您说的那样,哈希是基于(随机)盐,因此每次哈希都会不同。因此,您应该使用 .check_password(…)
function [Django-doc] 来验证它是否以某种方式匹配哈希变体:
from django.contrib.auth.hashers import <b>check_password</b>
class ProfileForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput(), required=False)
password2 = forms.CharField(widget=forms.PasswordInput(), required=False)
class Meta:
model = Employee
def __init__(self, *args, **kwargs):
self.user_id = kwargs.pop('user_id', None)
super(ProfileForm, self).__init__(*args, **kwargs)
def clean_password2(self):
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 != password2:
raise forms.ValidationError('Passwords do not match.')
user = User.objects.get(pk=self.user_id)
password_histories = PasswordHistory.objects.filter(
user=user
)
for pw in password_histories:
if <b>check_password(password2, pw.password)</b>:
raise forms.ValidationError('That password has already been used')
return password2
因此,如果我们找到与给定的 原始 密码匹配的散列密码,我们可以 return password
。如果在 for
循环结束时,我们没有找到任何这样的密码,我们可以 return password2
,否则我们会引发错误。
我有以下模型用于存储以前使用的散列密码:
class PasswordHistory(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
password = models.CharField(max_length=128, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now = True)
在更改密码表单中,我想检查用户要更改的新密码是否在过去 5 次没有被使用过。
这是我的表单验证:
class ProfileForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput(), required=False)
password2 = forms.CharField(widget=forms.PasswordInput(), required=False)
class Meta:
model = Employee
user_id = None
def __init__(self, *args, **kwargs):
self.user_id = kwargs.pop('user_id', None)
super(ProfileForm, self).__init__(*args, **kwargs)
def clean_password2(self):
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 != password2:
raise forms.ValidationError('Passwords do not match.')
user = User.objects.get(pk=self.user_id)
hashed_password = make_password(password1)
password_histories = PasswordHistory.objects.filter(
user=user,
password_hashed_password
)
if password_histories.exists():
raise forms.ValidationError('That password has already been used')
return password2
问题是密码每次都不一样,即使我一遍又一遍地尝试使用相同的明文密码。因此:
if password_histories.exists():
永远不会 returns 正确。
如果过去的密码由于加盐而总是不同,我如何比较过去的密码? 谢谢
.set_password
函数确实没有 return 任何东西,它只是 设置 密码。但是就像您说的那样,哈希是基于(随机)盐,因此每次哈希都会不同。因此,您应该使用 .check_password(…)
function [Django-doc] 来验证它是否以某种方式匹配哈希变体:
from django.contrib.auth.hashers import <b>check_password</b>
class ProfileForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput(), required=False)
password2 = forms.CharField(widget=forms.PasswordInput(), required=False)
class Meta:
model = Employee
def __init__(self, *args, **kwargs):
self.user_id = kwargs.pop('user_id', None)
super(ProfileForm, self).__init__(*args, **kwargs)
def clean_password2(self):
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 != password2:
raise forms.ValidationError('Passwords do not match.')
user = User.objects.get(pk=self.user_id)
password_histories = PasswordHistory.objects.filter(
user=user
)
for pw in password_histories:
if <b>check_password(password2, pw.password)</b>:
raise forms.ValidationError('That password has already been used')
return password2
因此,如果我们找到与给定的 原始 密码匹配的散列密码,我们可以 return password
。如果在 for
循环结束时,我们没有找到任何这样的密码,我们可以 return password2
,否则我们会引发错误。