Laravel将所有请求redirect到HTTPS

我们的整个网站将通过https服务。 我在每条路线上都有“https”。 但是,如果他们尝试通过HTTP,我如何将它们redirect到https?

Route::group(array('https'), function() { // all of our routes } 

使用App :: before

您可能可以利用app/filters.php文件中的App::before()块。

更改块以包括一个简单的检查,看看当前的请求是否安全,如果不是,redirect它。

 App::before(function($request) { if( ! Request::secure()) { return Redirect::secure(Request::path()); } }); 

使用filter

另一种select可能是像这样创build一个filter。 人们通常也将其存储在app/filters.php

 Route::filter('force.ssl', function() { if( ! Request::secure()) { return Redirect::secure(Request::path()); } }); 

然后,您可以将这个新filter强制执行到您的任何路由,路由组或控制器。

个人路线

 Route::get('something', ['before' => 'force.ssl'], function() { return "This will be forced SSL"; }); 

路线组

 Route::group(['before' => 'force.ssl'], function() { // Routes here. }); 

调节器

您需要在控制器的__construct()方法中执行此操作。

 public function __construct() { $this->beforeFilter('force.ssl'); } 

另一个答案可能是让你的Web服务器处理这个问题。 如果您使用的是Apache,则可以使用RedirectSSLfunction来确保所有请求都转到您站点的HTTPS版本,并且如果不redirect。 在Laravel甚至得到要求之前,这将会发生。

Apache RedirectSSL

如果你在NGINX上,你可以通过两个服务器块来完成。 一个用于端口80上的正常HTTPS,另一个用于端口443上的HTTPS。然后将普通服务器块configuration为始终redirect到ssl版本。

 server { listen 80; server_name mydomain.com; rewrite ^ https://$server_name$request_uri? permanent; } server { listen 443; server_name mydomain.com; ssl on; # other server config stuff here. } 

我个人会select这个选项,因为PHP本身不需要处理任何东西。 在Web服务器级别处理像这样的检查通常更便宜。

对于使用Laravel 4/5和Elastic Beanstalk的用户,使用这些方法强制HTTPS很困难,因为isSecure()将返回false 。 此外,使用.htaccessredirect将导致Chrome的redirect循环,并在Firefox中延迟页面加载时间。

这个设置是为了

  • Laravel 5并且可能为Laravel 3/4工作
  • 加载到运行EC2服务器实例的Elastic Beanstalk上的应用程序
  • 路由53用于DNSparsing
  • Cloudfront用于所有资产的全球CDN并实施HTTPS
  • 我在Windows机器上运行aws 。 Linux可能略有不同?

经过几个小时的尝试,我设法使用以下步骤将所有HTTP请求转发到HTTPS:

  1. 获得SSL证书。 指南和提供商很多,可以通过谷歌searchfind。

  2. 使用aws console命令将证书上传到AWS。 命令结构是:

     aws iam upload-server-certificate --server-certificate-name CERTIFICATE_NAME --certificate-body "file://PATH_TO_CERTIFICATE.crt" --private-key "file://YOUR_PRIVATE_KEY.pem" --certificate-chain "file://YOUR_CERTIFICATE_CHAIN.ca-bundle" --path /cloudfront/ 
  3. 创build一个Elastic Beanstalk应用程序。 继续安装过程。 一旦应用程序被设置,进入configuration – > networking层 – > 负载平衡 ,然后点击齿轮图标

  4. select安全侦听器端口443 。 selectProtocol作为HTTPS 。 从步骤2中selectCERTIFICATE_NAME以获取SSL证书ID 。 保存configuration。

  5. 转到您的控制台 。 点击EC2实例 。 点击负载平衡器 。 点击负载平衡器。 单击实例,然后向下滚动以查看分配给该负载均衡器的EC2实例。 如果EC2实例的名称与您的应用程序URL(或closures的)相同,请记下负载均衡器的DNS名称 。 它应该是格式awseb-e-...

  6. 回到你的控制台 。 点击CloudFront 。 点击创build分配 。 select一个Web分配。

  7. 设置分配。 将您的源域名设置为您在步骤5中find的负载均衡器DNS名称。 将查看器协议策略设置为将HTTPredirect到HTTPS 。 将转发查询string设置为 。 将备用域名(CNAME)设置为要用于应用程序的URL。 将SSL证书设置为您在步骤2中上传的CERTIFICATE_NAME 。 创build你的发行版。

  8. 在CloudFront中点击您的分配名称。 点击来源,select您的来源,然后点击编辑 。 确保您的Origin协议策略匹配查看器 。 回去。 点击行为 ,select您的来源,然后点击编辑 。 将转发标题更改为白名单并添加主机 。 保存。

  9. 转到您的控制台 。 点击路线53 。 点击托pipe区域 。 点击创build托pipe区域 。 设置你的域名。 一旦设置,点击创buildlogging集 。 input你的Alogging。 select别名 。 您的Alias Target是您的CloudFront分配。 保存logging。

  10. 为您的域设置名称服务器以指向Route 53名称服务器。 等待一切传播,这可能是几个小时。 转到您的url。 您将被自动redirect到HTTPS。

  11. “但是等等,我的链接不去HTTPS!? 您需要处理CloudFront将传递的X-Forwarded-Proto标头。 对于Laravel 4,请遵循本指南 。 对于Laravel 5,运行这个:

     php artisan make:middleware EB_SSL_Trust 

然后将其添加到EB_SSL_Trust文件中:

  public function handle($request, Closure $next) { $request->setTrustedProxies( [ $request->getClientIp() ] ); return $next($request); } 

并将其添加到您的App\Http\Kernel.php文件中:

  protected $middleware = [ ... 'App\Http\Middleware\EB_SSL_Trust', ... ]; 

注意:您的所有资产(如CSS,JS或图像)都需要通过HTTPS发送。 如果您使用Laravel创build这些链接,请使用secure_asset()在您的视图中创buildHTTPS URL。

使用.htaccess Apache的laravel 4.2.X

原始文件

 <IfModule mod_rewrite.c> <IfModule mod_negotiation.c> Options -MultiViews </IfModule> RewriteEngine On # Redirect Trailing Slashes... RewriteRule ^(.*)/$ /$1 [L,R=301] # Handle Front Controller... RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] </IfModule> 

编辑文件/public/.htaccess

  <IfModule mod_rewrite.c> <IfModule mod_negotiation.c> Options -MultiViews </IfModule> RewriteEngine On # Redirect Trailing Slashes... RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # Handle Front Controller... RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] </IfModule> 

Laravel 5.1中filter的使用已被废弃。 这对MiddleWare来说是一个完美的工作。

创build一个中间件,并在句柄部分放

 public function handle($request, Closure $next) { if(! $request->secure()) { return redirect()->secure($request->path()); } return $next($request); } 

然后,只需在Kernel.php中注册中间件,并将其用于路由或控制器。

结合以前的答案和更新Laravel 4.2:

 Route::filter('secure', function () { if (! Request::secure()) { return Redirect::secure( Request::path(), in_array(Request::getMethod(), ['POST', 'PUT', 'DELETE']) ? 307 : 302 ); } }); Route::when('*', 'secure'); 

如果你想redirect到相同的URL,但使用https,你应该使用Request::getRequestUri()而不是Request::path()

 App::before(function($request) { if( ! Request::secure()) { return Redirect::secure(Request::getRequestUri()); } }); 

如果有问题,由于某种原因, Request::secure()返回false,即使url是https ,也可能是因为$ _SERVER ['HTTPS']值不存在。

这是一个解决方法:

 App::before(function ($request){ // Force https if(!Request::secure() && array_get($_SERVER, 'SERVER_PORT') != 443){ return Redirect::secure(Request::path()); } }); 

我在执行POST请求时强制ssl有问题。 它总是会redirect到GET。 发生这种情况是因为Redirect::secure()默认使用302redirect。

为了确保你的POST请求被正确的redirect,使用类似的东西

 return Redirect::secure("your/path/here", 307) 

这将确保您的请求将在redirect发生后保持原始请求方法。

我不明白HTTP和HTTPS的详细,所以我很抱歉,如果这个答案不是很好。

我的理解是,即使客户端和(客户端指定的)服务器使用HTTPS, Request::secure()也会返回false,因为您的应用程序可能运行在不同的服务器上,可能不会收到https请求。

我在heroku托pipe我的laravel应用程序,似乎是这样做的。 我的猜测是,主(客户端指定的)服务器是一个负载平衡器,当请求被转发时,它作为一个普通的HTTP请求到达另一个服务器。

当这种转发可能发生时,您不应该只检查Request::secure()是否为true 。 我被指示(由#laravel @ irc.freenode.com中的某个人)也检查Request::server('HTTP_X_FORWARDED_PROTO') ,看它是否等于'https'

因此,如果您打算在此处遵循其他build议,并在不安全的情况下执行redirect,请尝试检查此服务器参数。

对于laravel 5.1,您应该使用App\Http\Providers\RouteServiceProvider@boot给定代码

 $router->filter('force.ssl', function () { if ( ! request()->secure() ) { return redirect()->secure(request()->path()); } }); 

现在你可以在路由文件中使用这个了。

 Route::group(['before' => 'force.ssl'], function () { // Routes here }); 

你也可以在$router->group()中join['before' => 'force.ssl']

 App\Http\Providers\RouteServiceProvider@map 

如果在代理和Request :: secure()后面不起作用。

 App::before( function( $request ) { // set the current IP (REMOTE_ADDR) as a trusted proxy Request::setTrustedProxies( [ $request->getClientIp() ] ); }); 

结合以前的答案来使用Laravel 4.2中的常量和方法。

routes.php文件

 Route::when('*', 'secure'); 

filters.php

 use Illuminate\Http\Response as IlluminateResponse; Route::filter('secure', function () { if ( ! Request::secure() && Request::getPort() != 443) { return Redirect::secure( Request::path(), in_array(Request::getMethod(), ['POST', 'PUT', 'DELETE']) ? IlluminateResponse::HTTP_TEMPORARY_REDIRECT : IlluminateResponse::HTTP_FOUND ); } }); 

如果你必须使用Laravel 4本身来处理redirect(像我一样),我会去下面的设置(解释代码中的注释):

路由filter:

 // app/filters.php Route::filter('ssl.force', function() { if(App::environment('production') && !Request::secure()) { // don't set a session cookie when redirecting to another scheme to // avoid dropping the session when switching scheme Config::set('session.driver', 'array'); // preserve query string while redirecting by using fullUrl() // instead of Redirect::secure + Request::path() $url = str_replace('http://', 'https://', Request::fullUrl()); return Redirect::to($url, 302, array(), true); } // secure cookies for https Config::set('session.secure', Request::secure()); }); 

然后将filter作为之前的filter应用于您的路由或路由组。 例如:

 // app/routes.php Route::group(array('before' => 'ssl.force'), function () { // SSL routes }); 

这在Apache 2.4中为我工作

我在Laravel的根文件夹中更改了.htaccess

<IfModule mod_rewrite.c> RewriteEngine On RewriteRule ^(.*)$ public/$1 [L] </IfModule>

<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] RewriteRule ^(.*)$ public/$1 [L] </IfModule>

这是Laravel 5.2.x或更高版本的备用解决scheme。

https://stackoverflow.com/a/39182378