假如我们部署的服务使用时间长了忘记了管理员密码,但具有操作数据库的权限,那可以将数据库down下来,改写密码字段的数据来找回密码。本文介绍一下数据库中的密码存储方式和比对原理:
密码存储原理
数据库中的密码是使用BCrypt哈希函数处理过后才进行存储的。BCrypt是一种密码哈希函数,设计的目标是防范彩虹表攻击。典型的数据库中的密码为以下这个字符串$2b$10$v.8FVedx5g49GaFJEZqz6eP0Nejbkb/QmLbNGRTCe/.iOI6d5z/dC
,可以分为四个部分:
-
2b
:这个部分表示哈希算法的版本,2b是BCrypt的一个版本。 -
10
:这个部分是"cost factor",也就是计算哈希值的消耗度。值越大,计算哈希值需要的时间就越长,存储的哈希值就越难破解; -
v.8FVedx5g49GaFJEZqz6e
:这个部分是盐值(Salt),它是一个随机值,用于和密码一起哈希,以防止两个相同的密码产生相同的哈希值。 -
P0Nejbkb/QmLbNGRTCe/.iOI6d5z/dC
:这个部分就是哈希过的密码。
如何验证密码
在验证用户密码时,你需要取出盐值和消耗度,然后使用同样的参数和用户输入的密码一起计算哈希值,如果计算出的哈希值和存储的哈希值相同,那么密码就是正确的。以下是一个示例代码,在忘记数据库密码时可以使用手动生成的密码改写数据库:
import bcrypt
# 输入的密码
password = "passwd".encode('utf-8')
# 生成盐值
# salt = bcrypt.gensalt()
salt = "$2b$10$v.8FVedx5g49GaFJEZqz6e".encode('utf-8')
# 哈希密码
hashed_password = bcrypt.hashpw(password, salt)
print(hashed_password)
# 密码验证
if bcrypt.checkpw(password, hashed_password):
print("密码正确")
else:
print("密码错误")
以上代码打印输入如下:
b'$2b$10$v.8FVedx5g49GaFJEZqz6eP0Nejbkb/QmLbNGRTCe/.iOI6d5z/dC'
密码正确
更改数据库密码
将数据库down下来,使用navicat等软件,打开数据库直接改写存储用户名和密码表中的密码字段为上述代码hashed_password
中的字符串即可将密码重置为"passwd"。