Laravel 8中payload突然变为NULL时如何解决“The payload is invalid”

问题描述

在尝试解密以前加密的密码时,我不断收到此错误

The payload is invalid.

这是相关的堆栈跟踪:

#0 /home/improojf/public_html/vendor/laravel/framework/src/Illuminate/Encryption/Encrypter.PHP(136): Illuminate\Encryption\Encrypter->getJsonPayload(NULL)
#1 /home/improojf/public_html/vendor/laravel/framework/src/Illuminate/Encryption/Encrypter.PHP(164): Illuminate\Encryption\Encrypter->decrypt('eyJpdiI6InloT0U...',false)
#2 /home/improojf/public_html/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.PHP(261): Illuminate\Encryption\Encrypter->decryptString('eyJpdiI6InloT0U...')
#3 /home/improojf/public_html/app/Models/Server.PHP(29): Illuminate\Support\Facades\Facade::__callStatic('decryptString',Array)
#4 /home/improojf/public_html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.PHP(473): Server->getpasswordAttribute('eyJpdiI6InloT0U...')

这里最大的问题是一个字符串在加密器代码随机变成了 NULL,这对我来说毫无意义。

这个问题的另一个问题是,有些记录只是按照广告的意图行事。

我用它做什么 这用于在数据库上存储 smtp/pop3 服务器的密码

我的尝试 这个问题完美解决,不加密/解密密码,搞砸了目的

它总是返回错误吗?没有,实际上有一些记录表现正常

我的猜测是什么 PHP artisan cache:clear 可能是其他地方报道的一个选项,但我认为应该有另一种解决方案。到目前为止,我已经(未经测试)以下访问器,而以前我只有第二次尝试/捕获

public function getpasswordAttribute($value){
    try {
        return Crypt::decryptString($value);
    } catch (\Illuminate\Contracts\Encryption\DecryptException $e) {
        \Illuminate\Support\Facades\Artisan::call('cache:clear');
    }
    try {
        return Crypt::decryptString($value);
    } catch (\Illuminate\Contracts\Encryption\DecryptException $e) {
        if(app()->runningUnitTests())
            return $value;
        else
            throw $e;
       }
}

解决方法

根据官方文档

Laravel 的加密服务提供了一个简单、方便的界面 用于使用 AES-256 和通过 OpenSSL 加密和解密文本 AES-128 加密。

Laravel 的所有加密值都使用消息签名 验证码 (MAC) 使它们的底层值不能被 修改或篡改一次

在使用 Laravel 的加密器之前,您必须在 config/app.php 配置文件中设置密钥配置选项。

这意味着加密解密取决于 app key 值。如果生成了新的应用密钥,那么旧的加密值将不适用于新的应用密钥

参考:https://laravel.com/docs/8.x/encryption

更新

问题是由于数据类型为 varchar(191),加密值部分存储在数据库表中。

最好将数据类型 varchar(191) 更改为 longtexttext