跳到主內容

【Laravel】部署在 SLB 或 Nginx 後面,要根據實際使用者請求是 HTTP 或 HTTPS

 

在 Laravel 中,當應用被部署在 SLB 或 Nginx 後面,要根據實際使用者請求是 HTTP 或 HTTPS,讓 Laravel 正確產生資源(asset/url)的協定 (http://https://),同時支援兩種不同呼叫來源(SLB 代理或 client 直連)。


✅ 關鍵目標:

Laravel 要根據 實際瀏覽器請求的協定而不是內部或 SLB 連線的協定)來產生正確的資源連結。


🧠 為什麼 Laravel 判斷會錯?

當你部署在 SLB 或 Nginx 反向代理後面時,Laravel 實際收到的請求是從 SLB 傳來的,Laravel 預設只看:

$_SERVER['HTTPS'] // on or off

這時它會誤以為是 HTTP,而不是使用者原本的 HTTPS。


✅ 正確作法:三步驟搞定 HTTP/HTTPS 自動判斷


✅ 步驟 1:設定 Laravel 的 TrustProxies

app/Http/Middleware/TrustProxies.php

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

class TrustProxies extends Middleware
{
   protected $proxies = '*'; // 或指定你的 proxy IP

   // protected $headers = Request::HEADER_X_FORWARDED_ALL; // 此為舊方法已廢棄感用以下預設
  
   protected $headers =
        Request::HEADER_X_FORWARDED_FOR |
        Request::HEADER_X_FORWARDED_HOST |
        Request::HEADER_X_FORWARDED_PORT |
        Request::HEADER_X_FORWARDED_PROTO |
        Request::HEADER_X_FORWARDED_AWS_ELB;
}

✅ 步驟 2:讓 SLB 或 Nginx 傳遞 X-Forwarded-Proto

📌 Nginx 範例(很關鍵):

location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;  # ⭐ 告訴 Laravel 真正協定是 http or https
}

📌 AWS ALB / 阿里雲 SLB 也會自動加上 X-Forwarded-Proto,你只需要 Laravel 信任它即可(Step 1)


✅ 步驟 3:確認 .env 有設 APP_URL(給 CLI 用)

APP_URL=https://your-domain.com

Laravel CLI 執行時(如:php artisan queue:work)沒有 request context,會 fallback 使用 APP_URL


🔍 驗證

在你的 Laravel 控制器或 middleware 中加這段:

dd([
    'secure' => request()->isSecure(),
    'scheme' => request()->getScheme(),
    'url' => request()->fullUrl(),
]);

你應該會看到:

[
  'secure' => true,
  'scheme' => 'https',
  'url' => 'https://your-domain.com/some/path'
]

或是在頁面上加上

 {{ request()->isSecure() ? 'HTTPS ✅' : 'HTTP ❌' }}
 <br>
 {{ url()->current() }}
 <br>

可以看到

image-1753348696262.png

如果前方沒有正確帶入(nginx 前面還有SLB),可以手動寫死

proxy_set_header X-Forwarded-Proto https;

✅ 小結:Laravel 正確產生 HTTP 或 HTTPS 協定連結的條件

項目 說明
TrustProxies 設定 必須設為 * + HEADER_X_FORWARDED_ALL
Proxy 傳 X-Forwarded-Proto Nginx / SLB 必須傳遞使用者實際協定
.envAPP_URL CLI 模式需 fallback 使用,請設為 https://...
使用 Laravel 的 asset(), url(), route() Laravel 會根據協定正確產生 URL