【问题标题】:Password hashing error in Django 3.1.4 - hashers.pyDjango 3.1.4 中的密码散列错误 - hashers.py
【发布时间】:2021-03-16 18:44:49
【问题描述】:

今天开始我的 Django 项目时出现错误:

'str' 对象没有属性'decode'

经过研究,我发现这是 django.contrib.auth 库中的 hashers.py 文件中的问题。它以某种方式停止工作我不确定是在 Django 更新之后还是其他任何事情之后。 当应用注册新用户或我尝试登录现有用户时会出现此错误。

我的登录用户代码如下所示(函数在views.py中调用):

from django.contrib.auth import authenticate

@api_view(["POST"])
@permission_classes((AllowAny,))
def login_user(request):
    email = request.data.get("email")
    password = request.data.get("password")
    user = authenticate(username=email, password=password)

来自 API 的 JSON 请求如下所示:

{
"email": "example@example.com",
"password":"mypassword"
}

这样注册用户的代码(在serializer.py中调用):

class RegisterSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'password', 'first_name', 'last_name', 'phone')
        extra_kwargs = {
            'password': {'write_only': True},
        }

    def create(self, validated_data):
        user = User.objects.create_user(
            username=validated_data['username'],
            email=validated_data['email'],
            password=validated_data['password'],
            first_name=validated_data['first_name'],
            last_name=validated_data['last_name'],
            phone=validated_data.get('phone', None)
        )
        return user

这也是我的用户模型类:

class User(AbstractUser):
email = models.EmailField(_('email'), unique=True)
username = models.CharField(_('username'), max_length=255, blank=True)
phone = PhoneField(_('phone'), blank=True)
status = models.IntegerField(_('status'), default=11)
avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)

USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []

class Meta:
    # db_table = 'label_user'
    verbose_name = _('user')
    verbose_name_plural = _('users')

def get_full_name(self):
    '''
    Returns the first_name plus the last_name, with a space in between.
    '''
    full_name = '%s %s' % (self.first_name, self.last_name)
    return full_name.strip()

def get_short_name(self):
    '''
    Returns the short name for the user.
    '''
    return self.first_name

def email_user(self, subject, message, from_email=None, **kwargs):
    '''
    Sends an email to this User.
    '''
    send_mail(subject, message, from_email, [self.email], **kwargs)

我尝试了什么:

  1. 降级 django 但没有帮助。
  2. 更新 Python 包也不会做任何改变。
  3. 创建新的 Python venv 并在启用和不启用 --no-cache-dir 标志的情况下再次安装所有软件包

我找到的解决方法:

我发现当我打开 hashers.py 文件时,应用程序会抛出错误并更改行:

 return "%s$%s" % (self.algorithm, data.decode('ascii'))

到:

return "%s$%s" % (self.algorithm, data)

效果很好。

还有其他方法可以解决这个问题吗?

【问题讨论】:

  • 你在哪里调用验证,密码变量和类型的内容是什么?验证数据['password'] 也是如此
  • @andreihondrari 我已经更新了帖子。
  • 升级后你对比过bcrypt库吗?看起来你使用 BCryptSHA256PasswordHasher 和 docstr 这个哈希器说Please be warned that this library depends on native C code and might cause portability issues. btw 之前你使用了什么 Django 版本?
  • @SergeiZherevchuk 我没有比较 bcrypt 版本,但我在更新到 3.1.4 之前使用了 django 3.0.7

标签: python django


【解决方案1】:

我找到了解决方案。我更新了 ubuntu 包和 pip 包:

apt update
apt upgrade
pip-review --local --interactive

然后我发现错误消息发生了变化:

'bcrypt' 对象没有属性 'ffi'

我找到that post 并检查我是否安装了多个 bcrypt 库。执行命令后:

pip3 list | grep bcrypt

我意识到我有bcrypt 包和py-bcrypt。我卸载了 py-bcrypt,一切都开始工作了。

另一个对我有用的选项是更改散列库。就像评论中提到的@Sergei Zherevchuk 一样:

请注意,此库依赖于本机 C 代码,可能会导致可移植性问题。

我在 settings.py 中更改了哈希库,来自:

PASSWORD_HASHERS = [
      'django.contrib.auth.hashers.BCryptSHA256PasswordHasher'
]

到(例如):

PASSWORD_HASHERS = [
      'django.contrib.auth.hashers.Argon2PasswordHasher'
]

我做的最后一步是使用命令安装 Argon2 django 库:

pip3 install django[argon2]

一切都在使用不同的哈希算法。

【讨论】:

    猜你喜欢
    • 2022-12-19
    • 2016-04-14
    • 1970-01-01
    • 1970-01-01
    • 2020-11-09
    • 1970-01-01
    • 2021-02-19
    • 2019-06-18
    • 2017-05-10
    相关资源
    最近更新 更多