Я недавно обновил свой проект с Laravel 5.6 до 5.7 и добавил шаги проверки электронной почты, описанные в документах Laravel, в мой проект.Все отлично работает на моей машине разработки (это http), но когда я обновляю свой рабочий сервер (который https) со всеми изменениями, то когда laravel отправляет мне электронное письмо со ссылкой (подписанный маршрут), сгенерированной для меня, чтобы нажать кнопку или вставитьв моем браузере laravel, похоже, не может проверить созданную им подпись.Побочный эффект - каждый раз, когда я нажимаю кнопку или вставляю ссылку в браузер, я получаю сообщение об ошибке:
403 Извините, у вас нет прав на доступ к этой странице.
Что я отследилДо сих пор я нашел код в классе ValidateSignature.php laravel и добавил несколько сообщений журнала.
public function handle($request, Closure $next)
{
Log::info('checking signature');
if ($request->hasValidSignature()) {
Log::info('signature is valid');
return $next($request);
}
Log::info('throwing InvalidSignatureException');
throw new InvalidSignatureException;
}
А более конкретно, я проследил точную проблему внутри модуля laravel UrlGenerator.php. Я добавил журналы вследующий метод:
public function hasValidSignature(Request $request)
{
$original = rtrim($request->url().'?'.Arr::query(
Arr::except($request->query(), 'signature')
), '?');
$expires = Arr::get($request->query(), 'expires');
$signature = hash_hmac('sha256', $original, call_user_func($this->keyResolver));
Log::info('url: '.$original);
Log::info('expire: '.$expires);
Log::info(' new signature: '.$signature);
Log::info('link signature: '.$request->query('signature', ''));
Log::info('hash equals: '.hash_equals($signature, $request->query('signature', '')));
Log::info('expired: '.!($expires && Carbon::now()->getTimestamp() > $expires));
return hash_equals($signature, $request->query('signature', '')) &&
! ($expires && Carbon::now()->getTimestamp() > $expires);
}
Когда я нажимаю кнопку или вставляю ссылку в браузере и нажимаю ввод, я получаю следующие сообщения журнала: (Я сменил реальный домен по понятным причинам .... не пытайтесь продать свойсайт или что-то еще)
checking signature
url: http://www.example.com/email/verify/2?expires=1538012234
expire: 1538012234
new signature: 1326b9e7402a51e0f05ddf1cb14f1e14852b4c5f0d1d6e726554806e7d85b4b1
link signature: e1d3ad5dc88faa8d8b0e6890ef60e216b75d26ef7ed5c6ab1cc661548e0ad8df
hash equals:
expired: 1
throwing InvalidSignatureException
Так что я не знаю, есть ли ошибка в логике, когда laravel создает начальную подпись или когда она пытается ее проверить.Однако, как я уже сказал, все отлично работает на моей машине для разработки.Я очистил кеш, очистил маршруты, обновил до последнего кода, перезагрузил сервер, все, что я могу придумать.Любая помощь будет принята с благодарностью.
**** ОБНОВЛЕНИЕ *****
Я вырыл немного глубже и сузил проблему.Я не могу поверить, что я не видел это прошлой ночью.Если мы внимательно посмотрим на выходные журналы, перечисленные выше, то одно сообщение журнала
url: http://www.example.com/email/verify/2?expires=1538012234
показывает нам проблему.Итак, как я уже говорил, моей машиной для разработки является http, а моим живым сервером - https.Сегодня утром (после хорошего 4-часового сна) я вижу, что журнал показывает нам, что каким-то образом логика метода hasValidSignature () получает маршрут с http вместо https.Поэтому, когда я возвращаюсь к своей электронной почте, ссылка в электронной почте - https, если я вставляю URL-адрес в своем браузере, он имеет https, а в моем браузере после этой логики возвращает ошибку 403, браузер по-прежнему показывает https.Итак, теперь мы можем сосредоточиться на том, как мой маршрут / URL конвертируется в http?Я действительно изо всех сил здесь, потому что я понятия не имею, как этот URL обрабатывается так или иначе, так как / email / verify даже не указан ни в одном из моих файлов маршрутов (о которых я знаю), и я не могу сказать, что понимаю, что искать вкапот для этого либо, поэтому я действительно надеюсь на некоторую помощь здесь.
Также вот настройки в моем файле .env:
APP_USE_HTTPS=true
APP_URL=https://www.example.com
APP_ENV=production
И в методе загрузки AppServiceProvider Iиметь
public function boot()
{
Schema::defaultStringLength(191);
if (env('APP_USE_HTTPS'))
{
Log::info('forcing URLs to use https');
\URL::forceScheme('https');
}