49.

常時 SSL 化(HTTPS リダイレクト)の完全ガイド(Apache / Nginx / Laravel /

編集
この記事の要点
  • 常時 SSL 化 = 全ての HTTP アクセスを HTTPS にリダイレクトする運用。SEO(Google が HTTPS を優遇)と機密性のため必須
  • Apache: .htaccessRewriteCond %{HTTPS} off + RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
  • Nginx: return 301 https://$host$request_uri; を 80 番ポートのサーバブロックに
  • Laravel: URL::forceScheme("https")AppServiceProvider::boot() に追加。config/session.phpsecure も true
  • HSTS ヘッダー Strict-Transport-Security: max-age=31536000; includeSubDomains でブラウザに HTTPS 強制を覚えさせる。SSL 証明書は Let's Encrypt (Certbot) で無料取得可能

常時 SSL 化(HTTPS リダイレクト)とは

ウェブサイト全体の通信を HTTPS にし、HTTP でアクセスされても自動的に HTTPS に転送する設定。SEO・セキュリティ・PWA / Service Worker の利用条件として必須です。Google Chrome は HTTP サイトに「保護されていない通信」と警告を出します。

Apache (.htaccess)

# .htaccess の先頭に
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# ロードバランサ(ALB / CloudFront)配下の場合は X-Forwarded-Proto を見る
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# HSTS ヘッダー(HTTPS で配信する設定にも追加)

  Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

Apache (httpd.conf / VirtualHost)


    ServerName example.com
    ServerAlias www.example.com
    Redirect permanent / https://example.com/



    ServerName example.com
    DocumentRoot /var/www/html

    SSLEngine on
    SSLCertificateFile      /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/example.com/privkey.pem

    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

Nginx

# /etc/nginx/sites-available/example.com
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # 推奨設定
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers off;

    # HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    root /var/www/html;
    index index.php index.html;

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        include fastcgi_params;
    }
}

Laravel での常時 SSL 化

セッション Cookie と CSRF Cookie も HTTPS のみに:

 env('SESSION_SECURE_COOKIE', true),  // HTTPS のみ送信
    'http_only' => true,
    'same_site' => 'lax',
];

// .env
APP_ENV=production
APP_URL=https://example.com
SESSION_SECURE_COOKIE=true

// ロードバランサ配下なら TrustProxies ミドルウェアも
// app/Http/Middleware/TrustProxies.php
protected $proxies = '*';  // ALB / CloudFront 信頼
protected $headers =
    Request::HEADER_X_FORWARDED_FOR |
    Request::HEADER_X_FORWARDED_HOST |
    Request::HEADER_X_FORWARDED_PORT |
    Request::HEADER_X_FORWARDED_PROTO;

Let's Encrypt で無料 SSL 証明書取得

# Ubuntu / Debian
sudo apt install certbot python3-certbot-nginx
# または Apache
sudo apt install certbot python3-certbot-apache

# Nginx 用に取得 + 自動設定
sudo certbot --nginx -d example.com -d www.example.com

# Apache 用
sudo certbot --apache -d example.com

# 証明書のみ取得(手動設定する場合)
sudo certbot certonly --standalone -d example.com

# 自動更新の確認(cron に登録済)
sudo certbot renew --dry-run
sudo systemctl list-timers | grep certbot

HSTS(HTTP Strict Transport Security)

ブラウザに「このドメインは絶対 HTTPS で来い」と覚えさせるヘッダー。一度送ると、以降ブラウザは HTTP リクエスト自体を発行しません:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

# max-age: 31536000 = 1年(秒)
# includeSubDomains: サブドメインも含む
# preload: Chrome の HSTS Preload List に登録申請可能
#   https://hstspreload.org/

注意: HSTS を有効にすると、その期間中 HTTP に戻せません。証明書切れで全アクセス不能になる事故が起きるので、最初は max-age=300(5分)で試して、問題なければ伸ばします。

混在コンテンツ (Mixed Content) の解消

HTTPS ページの中で http:// のリソース(img / script / iframe)を読むと、ブラウザがブロックします:










古い記事や CMS で http リンクが残っている場合、DB レベルで一括置換:

-- WordPress 等の例
UPDATE wp_posts
SET post_content = REPLACE(post_content, 'http://example.com', 'https://example.com');

UPDATE wp_options
SET option_value = REPLACE(option_value, 'http://example.com', 'https://example.com');

確認ツール

  • SSL Labs (ssllabs.com/ssltest/) - 証明書 / 設定の評価。A+ が目標
  • Why No Padlock? (whynopadlock.com) - 混在コンテンツ検査
  • Chrome DevTools - Security タブで詳細表示
  • HSTS Preload List (hstspreload.org) - ブラウザ組み込みリスト

SEO 観点での注意

  • 必ず 301 リダイレクト(恒久)を使う(302 は SEO 評価が継承されない)
  • Google Search Console に https 版のプロパティを別途登録
  • サイトマップ / canonical / hreflang / OGP も全部 https に更新
  • http 版 → https 版へ被リンクを保つため、リダイレクトを永続的に維持

FAQ

Q: 自己署名証明書でも常時 SSL 化できる?
A: 技術的に可能ですがブラウザが警告を出します。Let's Encrypt で無料の正規証明書を取得してください。

Q: 内部ネットワーク (社内) も HTTPS にすべき?
A: するべき。社内 CA を立てて配布するか、Cloudflare Origin CA 等を利用。

Q: ロードバランサで TLS 終端し、内部は HTTP の場合
A: 一般的構成。アプリ側で X-Forwarded-Proto を見て https と判定するように設定(Laravel の TrustProxies など)。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. インストールと設定
  2. クイックスタート & チュートリアル(初心者向け)
  3. クイックスタート & チュートリアル(中級者向け)
  4. ルーティング
  5. Bladeテンプレート(ビュー/レイアウト)
  6. コントローラー
  7. マイグレーションとテーブル定義
  8. データベースの設定
  9. Eloquentモデル (ORM)
  10. SQLとクエリビルダー
  11. バリデーション
  12. .envファイルの設定値へのアクセス
  13. 動作環境による分岐処理
  14. configフォルダ配下の設定値へのアクセス
  15. assetヘルパーを利用したpublicフォルダへのアクセス
  16. storageフォルダへのアクセス
  17. アプリケーション名の変更
  18. メンテナンス
  19. ログイン画面(認証システム)の作成
  20. ログインの必須化
  21. ログインユーザー情報の取得
  22. ルートの認証化
  23. 本番サーバーへのデプロイ方法
  24. 多言語化
  25. csrf_field
  26. ファイルのダウンロード
  27. CSVのアップロードおよび読み込み(maatwebsite/excel)
  28. ページタイトルの設定
  29. コマンド一覧
  30. エラー一覧
  31. SQLの実行ログ出力方法
  32. キャッシュのクリア
  33. Selectの結果の最初もしくは最後に任意の値を追加する方法
  34. ajaxでPOST通信する際の注意点
  35. ソーシャルログインの実装
  36. セッション情報の確認
  37. ログイン、ユーザー登録、パスワードリセット後のリダイレクト先の変更方法
  38. redirectやreturn viewにメッセージを付与する方法
  39. クッキー(cookie)の設定と取得
  40. クラスの再読み込み
  41. csrfの有効時間を変更する方法
  42. ViewComposerを用いてviewに共通の値を付与する方法
  43. View::shareを用いて共通の値を各ビューに渡す方法
  44. ミドルウェアを用いた処理の共通化
  45. Middleware内でAuth::check()などを使用する方法
  46. Controller以外でリダイレクトする方法
  47. セッションの値の取得/保存/更新/削除
  48. $requestの値を変更する方法
  49. 常時SSL化
  50. ページング(ページネーション)をする方法
  51. vue.jsとの連携
  52. Vue.jsと連携するSPA実行環境構築
  53. .envの値をvue.jsで参照する方法
  54. vue.jsを本番環境にリリースする方法
  55. could not find driver(Windows, MySQL編)