60

我们的整个网站将通过 https 提供服务。我在每条路线中都有“https”。但是,如果他们通过 http 进行尝试,我如何将他们重定向到 https?

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

15 回答 15

97

使用 App::before

您也许可以利用文件中的App::before()app/filters.php

更改块以包含一个简单的检查以查看当前请求是否安全,如果不安全,则重定向它。

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

使用过滤器

另一种选择可能是像这样创建一个过滤器。人们通常也将其存储在app/filters.php.

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

});

然后,您可以像这样对您的任何路由、路由组或控制器强制执行该新过滤器。

个人路线

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');
}
于 2013-11-14T02:50:40.110 回答
34

另一个答案可能是让您的网络服务器处理这个问题。如果您使用的是 Apache,您可以使用 RedirectSSL 功能来确保所有请求都转到您网站的 HTTPS 版本,如果没有重定向它们。这将在 Laravel 收到请求之前发生。

阿帕奇重定向SSL

如果你在 NGINX 上,你可以通过拥有两个服务器块来实现这一点。一个用于端口 80 上的普通 HTTPS,另一个用于端口 443 上的 HTTPS。然后将普通服务器块配置为始终重定向到 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.
}

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

于 2013-11-14T02:59:00.550 回答
11

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

此设置适用于

  • Laravel 5 并且可能适用于 Laravel 3 / 4
  • 加载到运行 EC2 服务器实例的 Elastic Beanstalk 上的应用程序
  • 用于 DNS 解析的 Route 53
  • Cloudfront 用于所有资产的全球 CDN 并强制执行 HTTPS
  • aws在 Windows 机器上运行。Linux 可能略有不同?

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

  1. 获取 SSL 证书。指南和提供者众多,可以通过 Google 搜索找到。

  2. aws使用控制台命令将证书上传到 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. 创建一个 Elastic Beanstalk 应用程序。继续完成设置过程。设置应用程序后,转到配置->网络层->负载平衡,然后单击齿轮图标

  4. 选择Secure listener port作为443。选择协议作为HTTPSCERTIFICATE_NAME步骤 2中选择SSL证书 ID。保存配置。

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

  6. 返回到您的控制台。单击CloudFront。单击创建分配。选择一个Web分发。

  7. 设置分布。将您的Origin Domain Name设置为您在步骤 5中找到的负载均衡器 DNS 名称。将查看器协议策略设置为将 HTTP 重定向到 HTTPS。将转发查询字符串设置为Yes。将备用域名 (CNAME)设置为要用于应用程序的 URL。将SSL 证书设置为您在步骤 2CERTIFICATE_NAME中上传的证书。创建您的发行版。

  8. 在 CloudFront 中单击您的分配名称。单击Origins,选择您的来源,然后单击Edit。确保您的Origin Protocol PolicyMatch Viewer。回去。单击Behaviors,选择您的来源,然后单击Edit将Forward Headers更改为Whitelist并添加Host。节省。

  9. 转到您的控制台。单击53 号公路。单击托管区域。单击创建托管区域。设置您的域名。设置完成后,单击Create Record Set。输入您的 A 记录。选择别名。您的别名目标是您的 CloudFront 分配。保存记录。

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

  11. “但是等等,我的链接没有转到 HTTPS!?” 您需要处理X-Forwarded-ProtoCloudFront 将传递的标头。对于 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 创建这些链接,请使用secure_asset()在您的视图中创建 HTTPS URL。

于 2015-03-20T16:43:19.583 回答
8

Laravel 5.1.*已弃用过滤。对于 MiddleWare 来说,这是一项完美的工作。

创建一个中间件并在句柄部分放置

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

然后只需在您的 Kernel.php 中注册您的中间件并将其与您的路由或控制器一起使用。

于 2016-02-07T14:05:51.920 回答
7

在 laravel 4.2.X 中使用 .htaccess Apache

原始文件

<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>
于 2014-10-23T16:38:48.690 回答
5

结合以前的答案并更新 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');
于 2014-08-22T19:47:30.727 回答
3

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

App::before(function($request)
{
    if( ! Request::secure())
    {
         return Redirect::secure(Request::getRequestUri());
    }
});
于 2015-09-02T15:24:56.200 回答
2

这在 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>

于 2017-07-27T18:13:10.583 回答
1

如果您遇到问题,由于某种原因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());
    }
});
于 2014-06-26T08:34:12.790 回答
1

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

为确保您的 POST 请求被正确重定向,请使用类似

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

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

于 2014-08-13T13:58:17.317 回答
1

我不太了解 HTTP 和 HTTPS,所以如果这个答案不是很好,我很抱歉。

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

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

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

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

于 2014-08-26T22:06:44.527 回答
1

对于 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
});

你也可以['before' => 'force.ssl']加入$router->group()

App\Http\Providers\RouteServiceProvider@map
于 2015-09-22T09:57:14.190 回答
0

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

App::before( function( $request )
{
  // set the current IP (REMOTE_ADDR) as a trusted proxy
  Request::setTrustedProxies( [ $request->getClientIp() ] );
});
于 2014-12-05T19:58:37.713 回答
0

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

路由.php

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

过滤器.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
        );
    }
});
于 2015-01-20T19:57:27.373 回答
0

如果您必须使用 Laravel 4 本身来处理重定向(像我一样),我会进行以下设置(解释为代码中的注释):

路由过滤器:

// 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());
});

然后将过滤器作为前过滤器应用到您的路由或路由组。例如:

// app/routes.php
Route::group(array('before' => 'ssl.force'), function () {
    // SSL routes
});
于 2016-05-10T03:25:39.910 回答