浅析 App_KEY 的作用
本文翻译自 APP_KEY And You
可能每个 Laravel 开发者新建或者克隆一个 Laravel 程序的时候,composer install
之后最可能以及最重要的的第一步操作就是生成 APP_KEY
。
在这篇文章中我们会讨论APP_KEY
能做的和不能做的,有些人会把用户密码的哈希处理与APP_KEY
相关联(实际上它们毫无关联)。
什么是 APP_KEY
每一个 Laravel 程序都会生成一个随机的32位长度的字符串存储在.env
文件中的APP_KEY
键值中,当我们新建 Laravel 项目的时候会自动为你创建一个,只有在克隆的时候你才有可能发现它没有被设定。
你可能看到过下面的错误,说明APP_KEY
没有设定
你可以自己手动生成或者使用 php artisan key:generate
来进行创建 APP_KEY
。
当你的应用程序执行的时候,只有一个地方会用到APP_KEY
:cookies。Laravel 使用它来加密所有的cookies,在将cookie返回给用户之前 Laravel 会对 cookie进行加密,然后再返回给用户,这样客户端就无法自己修改cookie来伪装成管理员或者其他用户了。
所以的加密和解密都在 Encrypter
中进行处理,其中主要使用了 [openssl_encrypt](https://secure.php.net/manual/en/function.openssl-encrypt.php)
进行加密。
有很多用户都会有一个误解,那就是APP_KEY
是用来处理用户哈希密码的。事实上不是这样的。Laravel的密码使用了 Hash::make()
或者 bcrypt()
来进行哈希处理,其中并没有用到APP_KEY
。
加密 VS 哈希
在 Laravel 中有两个主要的加密 Facade,分别是 Crypt
(对称加密) 和 Hash
(单向加密哈希)。密码是哈希,而cookie则是对称加密。
对称加密
假设我想发送一条加密的信息给我的好友A。我们商议好了一个用于加密和解密的key:
$key = "dont-panic";
当我想要发送一条只有上面的key能解锁的信息时,我们可以使用openssl_encrypt()
(Laravel 的 Crypt
也是使用的这个方法),具体如下:
$message = "So long and thanks for all the fish";
$key = "dont-panic";
$cipher = "AES-256-CBC";
echo openssl_encrypt($message, $cipher, $key);
// JJEK8L4G3BCfY0evXDRxUke2zqAzq6i7wL/Px4SjaEHXqt3x7hsj4+PhVQaH4ujX
此时,你就可以把这段加密的代码发送给A,然后他可以进行解密了。
$secret = "JJEK8L4G3BCfY0evXDRxUke2zqAzq6i7wL/Px4SjaEHXqt3x7hsj4+PhVQaH4ujX";
$key = "dont-panic";
$cipher = "AES-256-CBC";
echo openssl_decrypt($secret, $cipher, $key);
// So long and thanks for all the fish
Laravel的cookie加密解密也是同理,只不过key使用的是APP_KEY
。
单向哈希
当我们使用密码的时候,我们应当从不使用对称加密的方法,来避免用户可能解密密码。这表示Crypt
无法胜任,因此我们需要使用哈希方法,具有如下的特点:
- 快速:计算机能够快速的生成哈希值
- 确定性:针对同样的输入,输出是固定的
- 随机性:即使只更改一位字符串,哈希之后的输出应该十分不同
- 唯一性:碰撞概率应该非常非常的小
- 难于被暴力破解: 哈希之后的值应当难以被暴力破解
你应当听说过许多的单向哈希算法,例如md5
和 SHA-1
。在Laravel中使用了PHP的原生方法password_hash()
,它使用的哈希算法叫bcrypt
。
use Illuminate\Support\Facades\Hash;
$password = "dont-panic";
echo Hash::make($password);
// $2y$10$hEEF0lv4spxnvw5O4XyLZ.QjCE1tCu8HjMpWhmCS89J0EcSW0XELu
如果你曾经查看过users
数据表,那么上面的输出你可能会似曾相识。下面解释一下其中的含义:
$2y$
表示我们使用了blowfish
算法(bcrypt)10$
表示算法使用的 cost(值越高表示生成哈希的时间越长)hEEF0lv4spxnvw5O4XyLZ.
表示一个22位的随机“盐”QjCE1tCu8HjMpWhmCS89J0EcSW0XELu
哈希结果
由于这是一个单向哈希,因此我们无法进行解密,我们能做的只是去验证其是否匹配。
use Illuminate\Support\Facades\Hash;
$input = request()->get('password'); // "dont-panic"
$hash = '$2y$10$hEEF0lv4spxnvw5O4XyLZ.QjCE1tCu8HjMpWhmCS89J0EcSW0XELu';
return Hash::check($input, $hash);
// true
因此我们可以看到,在对称加密中我们使用到了APP_KEY
,而在密码哈希的时候我们是不需要使用它的。
总结
- 更改
APP_KEY
不会使用户的密码失效 - 更改
APP_KEY
会使session 和 cookie 失效,导致当前已登录用户退出登录 - 不要害怕你的
APP_KEY
- 如果你在其他地方使用了Laravel的加密方法,那么你需要制定一个计划来应对
APP_KEY
的更改
本作品采用《CC 协议》,转载必须注明作者和本文链接
我一直以为这个 APP_KEY 就是密码加密的时候的“盐”
文中链接404 了 https://learnku.com/docs/laravel/master/en...
@lovecn 改好了 :joy:
password_hash
加密,由于默认盐值是随机的,因此针对同样的输入,输出是不固定的。