menu-icon

LaravelでのURL生成ではまった点

クライアントとロードバランサー(以下、LB)がhttpsで通信していて、LBとWEBサーバーはhttpで通信している構成の場合、Laravelのasset()等のURL生成で少しはまったのでメモしておきます。

環境

クライアント <= https => AWS ELB <= http => AWS EC2インスタンス

問題

ページにhttpsでアクセスしても、リンク等のURLがhttpになっている。

原因

LB <-> EC2($_SERVER['HTTPS']はonでない)がhttp通信なので、デフォルトの状態だとhttpsの判定メソッド Symfony\Component\HttpFoundation\Request isSecure() でfalseが返ってしまい、生成されるURLがhttpとなります。

    public function isSecure()
    {
        if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) {
            return \in_array(strtolower($proto[0]), ['https', 'on', 'ssl', '1'], true);
        }

        $https = $this->server->get('HTTPS');

        return !empty($https) && 'off' !== strtolower($https);
    }

対応

App\Http\Middleware\TrustProxiesクラスを以下のように修正します。

app/Http/Middleware/TrustProxies.php
<?php

namespace App\Http\Middleware;

use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;

class TrustProxies extends Middleware
{
    /**
     * The trusted proxies for this application.
     *
     * @var array|string
     */
    protected $proxies = '*';

    /**
     * The headers that should be used to detect proxies.
     *
     * @var int
     */
    protected $headers = Request::HEADER_X_FORWARDED_AWS_ELB;
}

するとhttpsの判定に、X-Forwarded-Protoヘッダの情報を使用するようになるので、クライアント <=> LBがhttpsで通信していれば、生成されるURLもhttpsとなります。