LoginSignup
6
3

More than 5 years have passed since last update.

[Laravel5.4] Proxy環境下でSSL強制

Last updated at Posted at 2017-10-18

5年ほどROM専だったけど気が向いたので投稿。
最近業務でLaravel使うこと多くなってきた。

前提

  • Laravel 5.4
  • PHP7.1
  • AWS + CloudFront(CDN)
  • Port443空いてる Port80閉じてる

解決したいこと

まーあるあるネタ

  • 普通にLaravel使ってると、リダイレクト時やblade でリンク生成時、 最終的にUrlGeneratorでURL生成してることがほとんど
  • UrlGeneratorはアクセス元のスキームやホストからフルURLを生成する
  • Proxy環境下ではクライアントからのアクセスはHTTPSでも、エンドポイントから見るとHTTPなこと多し
  • よってUrlGeneratorがクライアント側がHTTPSでもhttpなURLを生成しちゃう

解決方法

ミドルウェアでリクエストを確認して、HTTPSなアクセスだったらスキーマを書き換える

ミドルウェア作成

app/Http/Middleware/SecureAccess.php
<?php
namespace App\Http\Middleware;

use \Symfony\Component\HttpFoundation\Request;

class SecureAccess
{
    public function handle($request, \Closure $next, $guard = null)
    {
        $is_secure =  $request->server('HTTPS') === 'on'
            || $request->server('HTTPS') === '1'
            || $request->server('SSL') === 'on'
            || $request->server('HTTP_X_FORWARDED_PROTO') === 'https'
            || $request->server('HTTP_CLOUDFRONT_FORWARDED_PROTO') === 'https'
        ;   // ※後述1

        if (! $is_secure) {
            return $next($request);
        }

        \URL::forceScheme('https'); // ※後述2

        Request::setTrustedProxies([
            '0.0.0.0/0'
        ]); // ※後述3

        return $next($request);
    }
}
  1. 大抵のProxy環境下ではHTTP_X_FORWARDED_PROTOでいけるはずだけど、
    CloudFront経由時は更にHTTP_CLOUDFRONT_FORWARDED_PROTOを見ないとダメだった。
    HTTPSかどうかの判定は他にもあるかも。
  2. UrlGenerator::forceScheme() のエイリアス。これでUrlGeneratorが返すURLが(ほぼ)httpsになる。
  3. 上記2の例外の対処で一部のURLを生成する関数は、
    forceScheme関係なくSymfonyのRequestオブジェクトからURLを生成している。
    そやつは $_SERVER['REMOTE_ADDR']とここでセットしたIPを判定しマッチしてればhttps、
    そうでなければ$_SERVER['HTTPS']のみを見てスキーマを返している。
    (正しくIP指定しないとローカル開発時の直HTTPSアクセスでProxy経由と判定されちゃうよ☆)

ミドルウェアの登録

あとは普通にミドルウェア登録。

app/Http/Kernel.php
<?php
namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    protected $middleware = [
        /* ~~ その他ミドルウェア ~~ */
        \App\Http\Middleware\SecureAccess::class,
        /* ~~ その他ミドルウェア ~~ */
    ];
}

所感

  • forceScheme 強制スキーマ(強制とは言ってない)
  • SymfonyのRequestクラスはホストはX_ORIGINAL_URLやらX_REWRITE_URLetc...見て大分がんばってるのに、
    スキーマだけはこういう判定方法にしてるのはなんか理由あるんかな?
6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3