web-dev-qa-db-ja.com

Laravel 5 - HTTPSにリダイレクト

私の最初のLaravel 5プロジェクトで作業していて、どこにどのようにロジックを配置して私のアプリにHTTPSを強制するかがわからない。ここでのクリンチャーは、アプリを指しているドメインが多数あり、3つのうち2つだけがSSLを使用していることです(3つ目はフォールバックドメイン、長い話)。そのため、これを.htaccessではなく、アプリのロジックで処理したいと思います。

Laravel 4.2では、filters.phpにあるこのコードでリダイレクトを達成しました。

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

私はミドルウェアがこのようなものが実装されるべき場所であると思っていますが、私はそれを使ってこれを理解することはできません。

ありがとうございます。

UPDATE

私のようにCloudflareを使用している場合は、コントロールパネルに新しいページルールを追加することでこれを実現できます。

94
NightMICU

あなたはそれをミドルウェアクラスで動作させることができます。私にあなたに考えを与えましょう。

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

次に、このミドルウェアをすべてのリクエストに適用して、次のように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'       

];

上記のサンプルでは、​​次の場合にミドルウェアはすべての要求をhttpsにリダイレクトします。

  1. 現在のリクエストにはセキュアプロトコル(http)はありません
  2. 環境がproductionと等しい場合だから、あなたの好みに合わせて設定を調整するだけです。

クラウドフレア

私は本番環境でWildCard SSLを使用してこのコードを使用していますが、コードは正しく機能します。 && App::environment() === 'production'を削除してlocalhostでテストすると、リダイレクトも機能します。したがって、SSLがインストールされているかどうかは問題ではありません。 Httpsプロトコルにリダイレクトされるためには、Cloudflareレイヤに非常に注意を払う必要があるようです。

編集23/03/2015

@Adam Linkの提案のおかげで:それはおそらくCloudflareが渡しているヘッダーによって引き起こされます。 CloudFlareはおそらくHTTP経由であなたのサーバーにヒットし、HTTPSリクエストを転送していることを宣言するX-Forwarded-Protoヘッダーを渡します。ミドルウェアに次のような行を追加する必要があります。

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

... CloudFlareが送信しているヘッダーを信頼する。これはリダイレクトループを停止します

編集27/09/2016 - Laravel v5.3

ミドルウェアクラスをkernel.php filewebグループに追加するだけです。

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

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

    ],
];

webグループはデフォルトですべてのルートに適用されるので、ルートやコントローラでwebを明示的に設定する必要はありません。

編集23/08/2018 - Laravel v5.7

  • 環境に応じてリクエストをリダイレクトするにはApp::environment() === 'production'を使用できます。以前のバージョンではenv('APP_ENV') === 'production'でした。
  • \URL::forceScheme('https');を使用しても実際にはリダイレクトされません。 Webサイトがレンダリングされたら、https://とのリンクを作成するだけです。
208
manix

AppServiceProviderで私のために働いた他のオプションは、ブートメソッドにこのコードを配置します。

\URL::forceScheme('https');

ForceScheme( 'https')の前に書かれた関数が間違っていました、そのforceScheme

49
Constantin Stan

あるいは、Apacheを使用している場合は、.htaccessファイルを使用して、URLにhttpsプレフィックスを使用するよう強制することができます。 Laravel 5.4では、私は私の.htaccessファイルに次の行を追加しました、そしてそれは私のために働きました。

RewriteEngine On

RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_Host}%{REQUEST_URI} [L,R=301]
23
Assad Ullah Ch

laravel 5.4では、.htaccessの代わりにhttpsリダイレクトを取得するためにこのフォーマットを使用します

namespace App\Providers;

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

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

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

これはLarave 5.2.x以降用です。 HTTPSを介してコンテンツを提供し、HTTPを介して他のコンテンツを提供するためのオプションが必要な場合は、ここで解決策が役立ちます。あなたは不思議に思うかもしれません、なぜ誰かがHTTPS経由で一部のコンテンツだけを提供したいのですか? HTTPS経由ですべてを提供しないのはなぜですか。

ただし、HTTPS経由でサイト全体にサービスを提供するのはまったく問題ありませんが、HTTPS経由ですべてを切断すると、サーバーに追加のオーバーヘッドが発生します。暗号化は安くはないことを忘れないでください。わずかなオーバーヘッドもアプリの応答時間に影響します。コモディティハードウェアは安価で、その影響はごくわずかだと主張するかもしれませんが、私は掘り下げています。だからここに行きます。これは、他の人がミドルウェアを使用して提案したものと似ていますが、HTTP/HTTPSを切り替えることができるフルソリューションです。

まずミドルウェアを作成します。

php artisan make:middleware ForceSSL

これがミドルウェアの外観です。

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

私は環境に基づいてフィルタリングしているのではないことに注意してください。私は、ローカルの開発用と本番用の両方のHTTPS設定を持っているので、必要はありません。

次の行を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,
];

次に、2つの基本的なグループログイン/サインアップなどと、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
});

ミドルウェアがコンソールからルートに正しく適用されていることを確認してください。

php artisan route:list

アプリケーションのすべてのフォームまたは機密領域を保護したので、ここで重要なのはビューテンプレートを使用して安全なリンクとパブリック(https以外)のリンクを定義することです。

上記の例に基づいて、あなたは次のようにあなたの安全なリンクをレンダリングするでしょう -

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

安全でないリンクは

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

これにより、 https:// yourhost/loginhttp:// yourhost/aboutus のような完全修飾URLが表示されます。

完全修飾URLをhttpでレンダリングしておらず、相対リンクURL( '/ aboutus')を使用している場合は、ユーザーがセキュリティで保護されたサイトにアクセスしてもhttpsが保持されます。

お役に立てれば!

6
na-98

Httpsリダイレクトを実現するために。htaccessファイルを使用するだけの場合はどうでしょうか。これは(パブリックフォルダではなく)プロジェクトルートに配置する必要があります。サーバーはプロジェクトのルートディレクトリを指すように設定する必要があります。

<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/$1 [L]
</IfModule>

私はこれをlaravel 5.4(この回答を書いている時点での最新版)に使用しますが、laravelが変更されたり機能が削除されたりしても機能バージョンでは引き続き機能します。

5
Maulik Gangani

あなたはあなたのindex.phpと同じフォルダ.htaccessにsslを強制するためにRewriteRuleを使うことができます。
画像添付として追加し、他のすべてのルールの前に追加してくださいsetting ssl .htaccess

5
Quy Le

indexController.phpに置く

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

        return redirect('/');
    }

    return view('index');
}

appServiceProvider.phpに置く

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

}

AppServiceProvider.phpでは、すべてのリダイレクトがhttps URLに送信され、httpリクエストの場合は1回リダイレクトする必要があるため、IndexController.phpでは1回リダイレクトする必要があります

3
Artur Qaramyan

上記の答えは私にはうまくいきませんでしたが、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]
3
Phil

Laravel 5.6では、動作させるために条件を少し変更する必要がありました。

から:

if (!$request->secure() && env('APP_ENV') === 'prod') {
return redirect()->secure($request->getRequestUri());
}

に:

if (empty($_SERVER['HTTPS']) && env('APP_ENV') === 'prod') {
return redirect()->secure($request->getRequestUri());
}
1
Priyank

これは私のためにうまくいきました。私はそれをhttpsに強制的にリダイレクトするためのカスタムphpコードを作りました。このコードをheader.phpに含めるだけです。

<?php
if (isset($_SERVER['HTTPS']) &&
    ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) ||
    isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
    $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  $protocol = 'https://';
}
else {
  $protocol = 'http://';
}
$notssl = 'http://';
if($protocol==$notssl){
    $url = "https://$_SERVER[HTTP_Host]$_SERVER[REQUEST_URI]";?>
    <script> 
    window.location.href ='<?php echo $url?>';
    </script> 
 <?php } ?>
1
Geeky Ashim

CloudFlareを使用している場合は、常にHTTPSを使用するようにページルールを作成するだけです。 Force SSL Cloudflare これはすべてのhttp://リクエストをhttps://にリダイレクトします。

それに加えて、あなたはあなたの\ app\Providers\AppServiceProvider.php boot()関数に次のようなものを追加する必要があるでしょう。

if (env('APP_ENV') === 'production' || env('APP_ENV') === 'dev') {
     \URL::forceScheme('https');
}

これにより、アプリ内のすべてのリンク/パスがhttp://ではなくhttps://を使用するようになります。

1
butaminas

これがHerokuのやり方です

ローカルではなくあなたのダイナにSSLを強制するには、public /のあなたの.htaccessの最後に追加してください:

# Force https on heroku...
# Important fact: X-forwarded-Proto will exist at your heroku dyno but wont locally.
# Hence we want: "if x-forwarded exists && if its not https, then rewrite it":
RewriteCond %{HTTP:X-Forwarded-Proto} .
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_Host}%{REQUEST_URI} [L,R=301]

あなたのローカルマシンでこれをテストすることができます:

curl -H"X-Forwarded-Proto: http" http://your-local-sitename-here

これは、ヘッダをherokuで受け取る形式にX転送するように設定します。

つまり、heroku dynoがどのようにリクエストを受け取るのかをシミュレートします。

あなたはあなたのローカルマシン上でこのレスポンスを得るでしょう:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://tm3.localhost:8080/">here</a>.</p>
</body></html>

それはリダイレクトです。上記のように.htaccessを設定した場合、それがherokuがクライアントに返すことになります。しかし、X転送が設定されていないので、それはあなたのローカルマシンでは起こりません(何が起こっているのかを見るために上記のcurlで偽造しました)。

1
mwal

Laravel 5.7でテストされた、少し異なるアプローチ

<?php

namespace App\Http\Middleware;

use Closure;

class ForceHttps
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $app_url = env('APP_URL');

        if ( !$request->secure() && substr($app_url, 0, 8) === 'https://' ) {
            return redirect()->secure($request->getRequestUri());
        }
        return $next($request);
    }
}
1
Zoli

私はLaravel 5.6.28次のミドルウェアで使用しています。

namespace App\Http\Middleware;

use App\Models\Unit;
use Closure;
use Illuminate\Http\Request;

class HttpsProtocol
{
    public function handle($request, Closure $next)
    {
        $request->setTrustedProxies([$request->getClientIp()], Request::HEADER_X_FORWARDED_ALL);

        if (!$request->secure() && env('APP_ENV') === 'prod') {
            return redirect()->secure($request->getRequestUri());
        }

        return $next($request);
    }
}
1
fomvasss

私はこの問題に多く苦しんだので、私はこの代替を加えています。私はいろいろな方法を試しましたが、何もうまくいきませんでした。だから、私はそれのための回避策を思い付きました。それは最善の解決策ではないかもしれませんがそれはうまくいきます -

参考までに、Laravel 5.6を使用しています

if (App::environment('production')) {
    URL::forceScheme('https');
}

production < - .envファイルのAPP_ENV値に置き換えます

1
thebrownkid

最も簡単な方法はアプリケーションレベルです。ファイル内

app/Providers/AppServiceProvider.php

以下を追加してください。

use Illuminate\Support\Facades\URL;

そしてboot()メソッドに以下を追加します。

$this->app['request']->server->set('HTTPS', true);
URL::forceScheme('https');

これにより、すべての要求がアプリケーションレベルでhttpsにリダイレクトされます。

(注:これはlaravel 5.5 LTSでテスト済みです)

0
Pinak Saha