我的服务器使用 SSL,因此我的所有路由/网址都使用 https。我最近在 Laravel 5.7 中发现了一个错误,该错误在尝试使用电子邮件验证时暴露出来,该错误在带有 https 的服务器上不起作用。我不会详细讨论该问题,因为我还有另一个问题。我想保持这个简单。 我的 .env 文件中有以下设置:
APP_USE_HTTPS=true
APP_URL=https://www.example.com
APP_ENV=production
我在 AppServiceProvider 的 boot() 方法中有以下内容
if (env('APP_USE_HTTPS')) {
Log::info('AppServiceProvider: forcing URLs to use https');
URL::forceScheme('https');
}
这可能有点过头了,但为了尝试解决这个问题,我还将以下代码放在我的 web.php 路由文件的顶部”
if (env('APP_USE_HTTPS')) {
Log::info('Routes: forcing URLs to use https');
URL::forceScheme('https');
}
Route::get('/', 'PublicController@getHome');
Route::get('home', 'PublicController@getHome');
然后在我的 PublicController.getHome() 方法中我放入以下代码:
public function getHome()
{
$currentPath= Request::fullUrl();
Log::info($currentPath);
return view('public.home');
}
现在我转到浏览器并在地址栏中输入:
https://www.example.com
我在日志文件中得到了这个:
AppServiceProvider: forcing URLs to use https
Routes: forcing URLs to use https
http://www.example.com
正如您从最后一条日志消息中看到的那样,laravel 始终使用 http 而不是 https 的事实开始产生问题。从签署的路线开始。我正在尝试使用内置电子邮件验证,但签名是使用 https 路由生成的,并且发送给用户的电子邮件的 URL 中确实有 https,用于返回同一服务器。然而,路由验证使用的是 http(即使使用了 https),因此它会生成不同的签名,因此所有验证链接都会失败并出现 403 错误。
我有什么遗漏的吗?我似乎找不到代码来显示 Laravel 如何知道使用 https 或 http,还是只是为 http 进行了硬编码?
感谢您给我的任何帮助。
*** 更新以显示 Shaielndra Gupta 答案的问题 ****
实现中间件后,下面是我使用的代码,但正如您将看到的,核心问题存在于处理 url 的所有方法中。例如:
$request->secure()
即使使用 https 也会返回 false。然后致电:
redirect()->secure($request->getRequestUri());
没有什么好处,因为这会导致路由再次循环回此方法,这仍然为 secure() 返回 false,基本上创建了一个无限循环(或无限太多的重定向)
class ForceHttpsProtocol {
public function handle($request, Closure $next) {
Log::info('request uri: '.$request->fullUrl());
Log::info('secure: '.($request->secure() ? 'yes' : 'no'));
if (!$request->secure() && env('APP_USE_HTTPS')) {
return redirect()->secure($request->getRequestUri());
}
return $next($request);
}
}
当您尝试访问任何页面 1 次时,即使使用 https://www.example.com
,上述代码的日志也会生成以下内容request uri: http://www.example.com
secure: no
request uri: http://www.example.com
secure: no
request uri: http://www.example.com
secure: no
request uri: http://www.example.com
secure: no
< over and over till page times out >
经过大量研究,我终于发现问题所在。 我的实时服务器安装在 Amazon EC2 服务器上位于负载均衡器后面。 负载均衡器正在接收 (https) 请求并处理所有 SSL 要求,然后将请求作为 http 转发到我的网站。 为了解决这个问题,我必须安装 fideloper/TrustedProxy 包。这个包允许我的网站信任代理并获取请求的有效标头,因此它现在知道请求实际上是使用 https 发送的。
Laravel 写了一篇文章,准确地描述了我的情况。 https://laravel-news.com/trusted-proxy
如果有人在 apache 代理方面遇到困难并且
$request->server()
您可以通过在
AppServiceProvider
中添加此行来覆盖请求库默认行为
$this->app['request']->server->set('HTTPS','on')
有一个非常有用的方法: 设置:
$this->app['request']->server->set('HTTPS','on');
而不是:
URL::forceScheme('https');
只有这样才能将页面链接http转为https。 当使用代理时。
改变这个
APP_USE_HTTPS=true
APP_URL=https://www.example.com
到此
APP_URL=http://www.example.com
APP_USE_HTTPS=false
因为 Laravel 使用 APP_URL 来生成 url。
改变你的
config/session.php
'http_only' => true,
更改为
'http_only' => false,
或者制作一个中间件 HttpsProtocol.php
namespace MyApp\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\App;
class HttpsProtocol {
public function handle($request, Closure $next)
{
if (!$request->secure() && App::environment() === 'production')
{
return redirect()->secure($request->getRequestUri());
}
return $next($request);
}
}
然后,将此中间件应用于每个请求,并在
protected $routeMiddleware array
中的 Kernel.php 文件中添加设置规则,
'https'=>App\Http\Middleware\HttpsProtocol::class