php Laravel 5 - 重定向到 HTTPS

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28402726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 23:50:46  来源:igfitidea点击:

Laravel 5 - redirect to HTTPS

phplaravellaravel-routinglaravel-5

提问by NightMICU

Working on my first Laravel 5 project and not sure where or how to place logic to force HTTPS on my app. The clincher here is that there are many domains pointing to the app and only two out of three use SSL (the third is a fallback domain, long story). So I'd like to handle this in my app's logic rather than .htaccess.

在我的第一个 Laravel 5 项目中工作,但不确定在哪里或如何放置逻辑以在我的应用程序上强制使用 HTTPS。这里的关键是有许多域指向应用程序,并且只有三分之二使用 SSL(第三个是后备域,长话短说)。所以我想在我的应用程序的逻辑中而不是 .htaccess 中处理这个问题。

In Laravel 4.2 I accomplished the redirect with this code, located in filters.php:

在 Laravel 4.2 中,我使用以下代码完成了重定向,位于filters.php

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

I'm thinking Middleware is where something like this should be implemented but I cannot quite figure this out using it.

我认为中间件是应该实现这样的东西的地方,但我无法完全弄清楚使用它。

Thanks!

谢谢!

UPDATE

更新

If you are using Cloudflare like I am, this is accomplished by adding a new Page Rule in your control panel.

如果您像我一样使用 Cloudflare,这是通过在您的控制面板中添加一个新的页面规则来实现的。

回答by manix

You can make it works with a Middleware class. Let me give you an idea.

您可以使其与中间件类一起使用。让我给你一个主意。

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

Then, apply this middleware to every request adding setting the rule at Kernel.phpfile, like so:

然后,将此中间件应用于在Kernel.php文件中添加设置规则的每个请求,如下所示:

protected $middleware = [
    'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
    'Illuminate\Cookie\Middleware\EncryptCookies',
    'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
    'Illuminate\Session\Middleware\StartSession',
    'Illuminate\View\Middleware\ShareErrorsFromSession',

    // appending custom middleware 
    'MyApp\Http\Middleware\HttpsProtocol'       

];

At sample above, the middleware will redirect every request to https if:

在上面的示例中,如果出现以下情况,中间件会将每个请求重定向到 https:

  1. The current request comes with no secure protocol (http)
  2. If your environment is equals to production. So, just adjust the settings according to your preferences.
  1. 当前请求没有安全协议 (http)
  2. 如果您的环境等于production. 因此,只需根据您的喜好调整设置即可。

Cloudflare

云耀斑

I am using this code in production environment with a WildCard SSL and the code works correctly. If I remove && App::environment() === 'production'and test it in localhost, the redirection also works. So, having or not a installed SSL is not the problem. Looks like you need to keep a very hard attention to your Cloudflare layer in order to get redirected to Https protocol.

我在带有 WildCard SSL 的生产环境中使用此代码,并且代码工作正常。如果我&& App::environment() === 'production'在本地主机中删除并测试它,重定向也有效。因此,是否安装 SSL 都不是问题。看起来您需要非常注意您的 Cloudflare 层才能重定向到 Https 协议。

Edit 23/03/2015

编辑 23/03/2015

Thanks to @Adam Link's suggestion: it is likely caused by the headers that Cloudflare is passing. CloudFlare likely hits your server via HTTP and passes a X-Forwarded-Proto header that declares it is forwarding a HTTPS request. You need add another line in your Middleware that say...

感谢@Adam Link的建议:这很可能是由 Cloudflare 传递的标头引起的。CloudFlare 可能通过 HTTP 访问您的服务器并传递一个 X-Forwarded-Proto 标头,声明它正在转发 HTTPS 请求。您需要在中间件中添加另一行说...

$request->setTrustedProxies( [ $request->getClientIp() ] ); 

...to trust the headers CloudFlare is sending. This will stop the redirect loop

...信任 CloudFlare 发送的标头。这将停止重定向循环

Edit 27/09/2016 - Laravel v5.3

编辑 27/09/2016 - Laravel v5.3

Just need to add the middleware class into webgroup in kernel.php file:

只需要将中间件类添加到web组中kernel.php file

protected $middlewareGroups = [
    'web' => [
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,

        // here
        \MyApp\Http\Middleware\HttpsProtocol::class

    ],
];

Remember that webgroup is applied to every route by default, so you do not need to set webexplicitly in routes nor controllers.

请记住,web默认情况下 group 应用于每个路由,因此您不需要web在路由或控制器中明确设置。

Edit 23/08/2018 - Laravel v5.7

编辑 23/08/2018 - Laravel v5.7

  • To redirect a request depending the environment you can use App::environment() === 'production'. For previous version was env('APP_ENV') === 'production'.
  • Using \URL::forceScheme('https');actually does not redirect. It just builds links with https://once the website is rendered.
  • 要根据环境重定向请求,您可以使用App::environment() === 'production'. 对于以前的版本是 env('APP_ENV') === 'production'.
  • 使用\URL::forceScheme('https');实际上不会重定向。它只是https://在网站呈现后建立链接。

回答by Constantin Stan

An other option that worked for me, in AppServiceProvider place this code in the boot method:

另一个对我有用的选项,在 AppServiceProvider 中将此代码放在引导方法中:

\URL::forceScheme('https');

The function written before forceScheme('https') was wrong, its forceScheme

forceScheme('https') 之前写的函数写错了,它的forceScheme

回答by Assad Ullah Ch

Alternatively, If you are using Apache then you can use .htaccessfile to enforce your URLs to use httpsprefix. On Laravel 5.4, I added the following lines to my .htaccessfile and it worked for me.

或者,如果您使用的是 Apache,那么您可以使用.htaccessfile 来强制您的 URL 使用https前缀。在 Laravel 5.4 上,我将以下几行添加到我的.htaccess文件中,它对我有用。

RewriteEngine On

RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

回答by Arun Yokesh

for laravel 5.4 use this format to get https redirect instead of .htaccess

对于 laravel 5.4 使用这种格式来获取 https 重定向而不是 .htaccess

namespace App\Providers;

use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        URL::forceScheme('https');
    }
}

回答by Mladen Janjetovic

Similar to manix's answer but in one place. Middleware to force HTTPS

类似于 manix 的答案,但在一个地方。强制HTTPS的中间件

namespace App\Http\Middleware;

use Closure;

use Illuminate\Http\Request;

class ForceHttps
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (!app()->environment('local')) {
            // for Proxies
            Request::setTrustedProxies([$request->getClientIp()]);

            if (!$request->isSecure()) {
                return redirect()->secure($request->getRequestUri());
            }
        }

        return $next($request);
    }
}

回答by na-98

This is for Larave 5.2.x and greater. If you want to have an option to serve some content over HTTPS and others over HTTP here is a solution that worked for me. You may wonder, why would someone want to serve only some content over HTTPS? Why not serve everything over HTTPS?

这适用于 Larave 5.2.x 及更高版本。如果您想选择通过 HTTPS 提供某些内容而通过 HTTP 提供其他内容,这里有一个对我有用的解决方案。您可能想知道,为什么有人只想通过 HTTPS 提供某些内容?为什么不通过 HTTPS 提供所有服务?

Although, it's totally fine to serve the whole site over HTTPS, severing everything over HTTPS has an additional overhead on your server. Remember encryption doesn't come cheap. The slight overhead also has an impact on your app response time. You could argue that commodity hardware is cheap and the impact is negligible but I digress :) I don't like the idea of serving marketing content big pages with images etc over https. So here it goes. It's similar to what others have suggest above using middleware but it's a full solution that allows you to toggle back and forth between HTTP/HTTPS.

虽然通过 HTTPS 为整个站点提供服务是完全没问题的,但是通过 HTTPS 切断所有内容会给您的服务器带来额外的开销。请记住,加密并不便宜。轻微的开销也会影响您的应用程序响应时间。你可能会争辩说商品硬件很便宜,影响可以忽略不计,但我离题了:) 我不喜欢通过 https 提供带有图像等的营销内容大页面的想法。所以就到这里了。它类似于上面使用中间件的其他人建议,但它是一个完整的解决方案,允许您在 HTTP/HTTPS 之间来回切换。

First create a middleware.

首先创建一个中间件。

php artisan make:middleware ForceSSL

This is what your middleware should look like.

这就是你的中间件应该是什么样子。

<?php

namespace App\Http\Middleware;

use Closure;

class ForceSSL
{

    public function handle($request, Closure $next)
    {

        if (!$request->secure()) {
            return redirect()->secure($request->getRequestUri());
        }

        return $next($request);
    }
}

Note that I'm not filtering based on environment because I have HTTPS setup for both local dev and production so there is not need to.

请注意,我没有根据环境进行过滤,因为我为本地开发和生产都设置了 HTTPS,因此不需要。

Add the following to your routeMiddleware \App\Http\Kernel.php so that you can pick and choose which route group should force SSL.

将以下内容添加到您的 routeMiddleware \App\Http\Kernel.php,以便您可以选择应该强制 SSL 的路由组。

    protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'can' => \Illuminate\Foundation\Http\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'forceSSL' => \App\Http\Middleware\ForceSSL::class,
];

Next, I'd like to secure two basic groups login/signup etc and everything else behind Auth middleware.

接下来,我想保护两个基本组登录/注册等以及 Auth 中间件背后的所有其他内容。

Route::group(array('middleware' => 'forceSSL'), function() {
/*user auth*/
Route::get('login', 'AuthController@showLogin');
Route::post('login', 'AuthController@doLogin');

// Password reset routes...
Route::get('password/reset/{token}', 'Auth\PasswordController@getReset');
Route::post('password/reset', 'Auth\PasswordController@postReset');

//other routes like signup etc

});


Route::group(['middleware' => ['auth','forceSSL']], function()
 {
Route::get('dashboard', function(){
    return view('app.dashboard');
});
Route::get('logout', 'AuthController@doLogout');

//other routes for your application
});

Confirm that your middlewares are applied to your routes properly from console.

从控制台确认您的中间件已正确应用于您的路由。

php artisan route:list

Now you have secured all the forms or sensitive areas of your application, the key now is to use your view template to define your secure and public (non https) links.

现在您已经保护了应用程序的所有表单或敏感区域,现在的关键是使用您的视图模板来定义您的安全和公共(非 https)链接。

Based on the example above you would render your secure links as follows -

根据上面的示例,您将按如下方式呈现您的安全链接 -

<a href="{{secure_url('/login')}}">Login</a>
<a href="{{secure_url('/signup')}}">SignUp</a>

Non secure links can be rendered as

非安全链接可以呈现为

<a href="{{url('/aboutus',[],false)}}">About US</a></li>
<a href="{{url('/promotion',[],false)}}">Get the deal now!</a></li>

What this does is renders a fully qualified URL such as https://yourhost/loginand http://yourhost/aboutus

这样做是呈现一个完全合格的 URL,例如https://yourhost/loginhttp://yourhost/aboutus

If you were not render fully qualified URL with http and use a relative link url('/aboutus') then https would persists after a user visits a secure site.

如果您没有使用 http 呈现完全限定的 URL 并使用相对链接 url('/aboutus') 那么 https 将在用户访问安全站点后持续存在。

Hope this helps!

希望这可以帮助!

回答by Maulik Gangani

What about just using .htaccessfile to achieve https redirect? This should be placed in project root (not in public folder). Your server needs to be configured to point at project root directory.

仅使用.htaccess文件来实现 https 重定向怎么样?这应该放在项目根目录中(而不是在公共文件夹中)。您的服务器需要配置为指向项目根目录。

<IfModule mod_rewrite.c>
   RewriteEngine On
   # Force SSL
   RewriteCond %{HTTPS} !=on
   RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
   # Remove public folder form URL
   RewriteRule ^(.*)$ public/ [L]
</IfModule>

I use this for laravel 5.4 (latest version as of writing this answer) but it should continue to work for feature versions even if laravel change or removes some functionality.

我将它用于 laravel 5.4(撰写此答案时的最新版本),但即使 laravel 更改或删除某些功能,它也应继续适用于功能版本。

回答by Quy Le

You can use RewriteRule to force ssl in .htaccess same folder with your index.php
Please add as picture attach, add it before all rule otherssetting ssl .htaccess

您可以使用 RewriteRule 在 .htaccess 与您的 index.php 相同的文件夹中强制 ssl
请添加为图片附件,在所有其他规则之前添加设置 ssl .htaccess

回答by Artur Qaramyan

in IndexController.php put

在 IndexController.php 中放入

public function getIndex(Request $request)
{
    if ($request->server('HTTP_X_FORWARDED_PROTO') == 'http') {

        return redirect('/');
    }

    return view('index');
}

in AppServiceProvider.php put

在 AppServiceProvider.php 中放入

public function boot()
{
    \URL::forceSchema('https');

}

}

In AppServiceProvider.php every redirect will be go to url https and for http request we need once redirect so in IndexController.php Just we need do once redirect

在 AppServiceProvider.php 中,每次重定向都会转到 url https,对于 http 请求,我们需要一次重定向,因此在 IndexController.php 中只需要进行一次重定向

回答by Phil

The answers above didn't work for me, but it appears that Deniz Turan rewrote the .htaccess in a way that works with Heroku's load balancer here: https://www.jcore.com/2017/01/29/force-https-on-heroku-using-htaccess/

上面的答案对我不起作用,但似乎 Deniz Turan 以与 Heroku 负载均衡器一起使用的方式重写了 .htaccess:https: //www.jcore.com/2017/01/29/force-https -on-heroku-using-htaccess/

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]