Случайное исключение RuntimeException: единственными поддерживаемыми шифрами являются AES-128-CBC и AES-256-CBC с правильной длиной ключа
У меня такая же проблема с Laravel 5.3 (на сервере Windows). Я сделал все возможные попытки: проверить файл .env, config, новое поколение ключей artisan, кеш: очистить, настроить: очистить, добавить композитор, но проблема случайным образом сохраняется.
Обратите внимание, что тот же код с точно такой же версией apache, mysql, php, не создает эту проблему в Mac OS.
Я обнаружил, что ключ (первый параметр Encrypter constractor) приходит "иногда" пустым, и, конечно, он терпит неудачу. В большинстве случаев ключ является правильным, но случайным образом ключ прибывает пустым из EncryptionServiceProvider, который по очереди запрашивает его в конфигурации приложения.
Таким образом, единственным решением, которое сработало для меня, было добавить if ($key)
в EncryptionServiceProvider, чтобы конструктор шифрования не вызывался с пустым ключом.
Конечно, это не "чистое" решение, и оно не объясняет проблему, но, по крайней мере, позволяет найти файл журнала, заполненный ошибкой:
RuntimeException: единственными поддерживаемыми шифрами являются AES-128-CBC и AES-256-CBC и страницы отображаются правильно.
Если это ошибка Laravel, я не знаю, но, конечно, если кто-то может это объяснить, я буду более счастлив узнать.
Ниже мой модифицированный класс: я просто добавил строку if ($key)
до new Encrypter
:
class EncryptionServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->singleton('encrypter', function ($app) {
$config = $app->make('config')->get('app');
// If the key starts with "base64:", we will need to decode the key before handing
// it off to the encrypter. Keys may be base-64 encoded for presentation and we
// want to make sure to convert them back to the raw bytes before encrypting.
if (Str::startsWith($key = $config['key'], 'base64:')) {
$key = base64_decode(substr($key, 7));
}
if ($key)
return new Encrypter($key, $config['cipher']);
});
}
}
Дополнительная информация и журнал возврата:
Конечно, по мере того как я писал, я проверил файл .env, конфигурацию, новое поколение ключей artisan, cache: clear, config: clear, composer update.
Этот материал в порядке, так как он работает 99% времени, но случайно я получаю ошибку.
Здесь обратная трассировка:
[2017-01-09 10:25:40] test.ERROR: RuntimeException: поддерживается только поддержка Шифрами являются AES-128-CBC и AES-256-CBC с правильной длиной ключа. в C:\Apache24\HTDOCS\сф\поставщика\Laravel\рамки\SRC\Осветите\Encryption\Encrypter.php: 43
Трассировка стека:
#0 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Encryption\EncryptionServiceProvider.php(27): Illuminate\Encryption\Encrypter->__construct('', 'AES-256-CBC')
#1 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(746): Illuminate\Encryption\EncryptionServiceProvider->Illuminate\Encryption\{closure}(Object(Illuminate\Foundation\Application), Array)
#2 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(644): Illuminate\Container\Container->build(Object(Closure), Array)
#3 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(709): Illuminate\Container\Container->make('encrypter', Array)
#4 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(864): Illuminate\Foundation\Application->make('encrypter')
#5 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(819): Illuminate\Container\Container->resolveClass(Object(ReflectionParameter))
#6 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(788): Illuminate\Container\Container->getDependencies(Array, Array)
#7 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Container\Container.php(644): Illuminate\Container\Container->build('App\\Http\\Middle...', Array)
#8 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(709): Illuminate\Container\Container->make('App\\Http\\Middle...', Array)
#9 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(127): Illuminate\Foundation\Application->make('App\\Http\\Middle...')
#10 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#11 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\View\Middleware\ShareErrorsFromSession.php(49): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#12 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(137): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#13 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#14 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Session\Middleware\StartSession.php(64): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#15 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(137): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#16 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#17 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse.php(37): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#18 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(137): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#19 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#20 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(104): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#21 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Router.php(655): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#22 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Router.php(629): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#23 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Router.php(607): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#24 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(268): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#25 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(53): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))
#26 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode.php(46): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#27 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(137): Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
#28 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#29 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(104): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#30 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(150): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#31 C:\Apache24\htdocs\sph\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(117): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#32 C:\Apache24\htdocs\sph\public\index.php(53): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#33 {main}
Ответы
Ответ 1
Проблема возникает при использовании поточно-безопасных версий PHP на многопоточных веб-серверах вместо многопроцессорных веб-серверов. Вы можете прочитать о проблеме немного подробнее о проблема Github здесь, Github здесь, а отчет об ошибке PHP здесь. Есть еще несколько ссылок, но они просто отделены от тех немногих, что я опубликовал.
Основной смысл заключается в том, что с многопоточным веб-сервером у вас есть один процесс, который обрабатывает несколько потоков. Однако методы putenv()
/getenv()
не являются потокобезопасными и изменяют переменные среды на уровне процесса, поэтому затрагиваются все потоки под этим процессом.
Итак, у вас получилось что-то вроде этого: (как описано в этой проблеме):
Request 1: {starts --- loads env --- work --- finishes}
Request 2: {starts ----- loads env --- work --- finishes}
Итак, запрос 1 входит, загружает среду и работает. Пока запрос 1 работает, запрос 2 входит и запускается в другом потоке. Перед запросом 2 читает переменные среды, запрашивает 1 финиширует, а PHP очищает все переменные, заданные putenv()
. Теперь попросите 2 попытки прочитать среду, но получает null
, потому что переменные были очищены при завершении запроса 1.
Эта проблема может быть смягчена двумя способами:
-
Не используйте файл .env
. Задайте переменные среды напрямую и отключите phpdotenv. Это также предлагается пакетом :
phpdotenv предназначен для среды разработки и обычно не должен использоваться в производстве. В процессе производства фактические переменные среды должны быть установлены так, чтобы не было накладных расходов на загрузку файла .env для каждого запроса.
-
Никогда не используйте метод env()
вне файлов конфигурации и убедитесь, что вы кешируете свои файлы конфигурации. Используя этот метод, среда читается один раз: при создании кеша конфигурационного файла. Каждый фактический веб-запрос будет считывать данные из кеша, а переменные окружения никогда не будут затронуты снова.
Ответ 2
Я установил Laravel 5.3, и я не нашел там файл .env. И бум... Это была проблема. Я создал файл .env в корневом каталоге приложения и запустил
php artisan key: generate
в терминале, и он сгенерировал строку с кодировкой base 64 в терминале. Скопируйте эту строку в .ENV файл как
APP_KEY = base64: ******************************************* *****
где **** генерируется закодированная строка. Запустите приложение еще раз, и оно должно работать.
Ответ 3
Это так просто, скопируйте файл APP_KEY
из .env
в config/app.php -> key
или выполните следующую команду:
php artisan key:generate