我发现,人的表达欲是看场景的,当涉及到我最感兴趣的技术类的话题时,我其实就知道该说什么了。
最近在搞一个简单的后台管理的源码的二次开发,原项目中,不允许直接在后台添加用户,只能通过注册,或者前期初始化的时候实现。最终,在GPT的协助下,我完成了这个工作。
首先,通过阅读源码,我发现项目中的密码不是明文存放(这个年头了,不会真有人还明文吧),是经过加密的,加密代码如下
1 | const hashedPassword = bcrypt.hashSync(password, 10); |
于是,我就让GPT根据这行命令给我写了一个脚本,结果如下
1 | // encryptPassword.js |
然后,我就发现了一个问题,那就是两次哈希的结果,居然是不一样的
1 | $ node encryptPassword.js 123456 |
我第一次遇到这个情况,于是我把结果返回给了了GPT,它给的回复如下:
两次加密结果不一样是因为 bcryptjs 使用了盐(salt)的概念来增加密码的安全性。盐是一个随机生成的值,与密码混合后进行哈希运算,生成最终的加密结果。
每次调用 bcrypt.hashSync
方法时,bcryptjs 会生成一个新的随机盐,然后将该盐与密码混合后进行哈希运算。因此,即使输入的密码相同,由于使用了不同的盐,最终生成的加密结果也会不同。
这种做法是为了增加密码的安全性,即使两个用户使用相同的密码,最终的加密结果也是不同的。这样做可以避免通过比较加密结果来判断用户是否使用相同的密码。
如果需要在后续验证密码时,可以使用 bcrypt.compareSync
方法将输入的密码与存储的加密结果进行比较,bcryptjs 内部会自动提取盐并进行相应的比较验证。
原来如此,于是我让GPT写一个测试脚本,让我来测试下,是不是真的如此
1 | //comparePasswords.js |
我运行之后,发现两个不match啊,GPT你是不是骗我
1 | $ node comparePasswords.js 123456 $2b$12$RJhc7WSsbRhkg2QxZuDG6.qgPXhFlrbvfOtw0SWDHkElgt1thSPD2 |
当我把这段内容给GPT时,它敏锐的观察到,我的输入有问题,它的回复如下
在你的示例中,你在命令行中传递了哈希值作为一个参数。这在许多命令行解释器中可能会引起问题,因为哈希字符串中的$
符号可能会被视为变量的开头,然后尝试去解析它。结果就是,你的程序可能没有接收到完整的哈希字符串,而是只接收到了一部分。
你可以尝试用引号将哈希字符串括起来,以避免命令行解释器对$
符号进行解析。
你的命令应该这样写:
1 | node comparePasswords.js 123456 "$2b$12$RJhc7WSsbRhkg2QxZuDG6.qgPXhFlrbvfOtw0SWDHkElgt1thSPD2" |
在这个版本中,哈希字符串被括在双引号中,这会防止命令行解释器将$
符号视为变量的开头。
看来可能是因为$
导致的。不过遗憾的是,我运行上述的代码还是失败了。因为$
在双引号内还是会作为变量的开头,使用单引号才行,因此正确形式是
1 | node comparePasswords.js 123456 '$2b$12$RJhc7WSsbRhkg2QxZuDG6.qgPXhFlrbvfOtw0SWDHkElgt1thSPD2' |
不管如何,我在GPT的帮助下,了解了一个新的库,Bcrypt,还知道了它能够保证每次加密的结果都是随机的,但又保证了,同一个密码能够正确的验证。比如说我让GPT写了一个python版本,虽然输出的结果很不一样,但是依旧能够通过验证。