

.htaccessを編集していますが、思い通り動作せず皆様のお力添えを頂きたく思います。

* * *

  1. **したいこと:**

    * HTTPアクセスをHTTPSに統一
  2. **状況:**

    * リダイレクトループになってしまう。
  3. **環境:**

    * AWS ロードバランサー でSSL設定済み
    * Apache 2.4
    * Laravel5.1LTS  
.htaccessはLaravel5.1にあったものを編集しています。

  4. **他:**

    * .htaccessとログを記載します。

* * *

_.htaccess_

[code]

    <IfModule mod_rewrite.c>
        <IfModule mod_negotiation.c>
            Options -MultiViews
        </IfModule>
    
        RewriteEngine On
    
        # Redirect Trailing Slashes If Not A Folder...
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)/$ /$1 [L,R=301]
    
        # Handle Front Controller...
        RewriteCond %{HTTPS} on # HTTPSアクセスの場合
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f # ファイルが存在しない場合
        RewriteRule . index.php [L] # index.phpに書き換えて終了
    
        RewriteCond %{HTTPS} off # HTTPアクセスの場合
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule . https://%{HTTP_HOST}%{REQUEST_URI} [L,R] # https://ホスト名/URI にリダイレクトし終了
    
    </IfModule>
    
[/code]

_ログ_ （主要な部分を抜き出しています）

[code]

    add path info postfix: /var/www/html/path -> /var/www/html/path/to
    strip per-dir prefix: /var/www/html/path/to -> path/to
    applying pattern '^(.*)/$' to uri 'path/to'
    add path info postfix: /var/www/html/path -> /var/www/html/path/to
    strip per-dir prefix: /var/www/html/path/to -> path/to
    applying pattern '.' to uri 'path/to'
    RewriteCond: input='off' pattern='on' => not-matched
    add path info postfix: /var/www/html/path -> /var/www/html/path/to
    strip per-dir prefix: /var/www/html/path/to -> path/to
    applying pattern '.' to uri 'path/to'
    RewriteCond: input='off' pattern='off' => matched
    RewriteCond: input='/var/www/html/path' pattern='!-d' => matched
    RewriteCond: input='/var/www/html/path' pattern='!-f' => matched
    rewrite 'path/to' -> 'https://myhostname/path/to'
    explicitly forcing redirect with https://myhostname/path/to
    escaping https://myhostname/path/to for redirect
    redirect to https://myhostname/path/to [REDIRECT/302]  -->ここまでをループしている
    add path info postfix: /var/www/html/path -> /var/www/html/path/to
    strip per-dir prefix: /var/www/html/path/to -> path/to
    applying pattern '^(.*)/$' to uri 'path/to'
    add path info postfix: /var/www/html/path -> /var/www/html/path/to
    strip per-dir prefix: /var/www/html/path/to -> path/to
    applying pattern '.' to uri 'path/to'
    RewriteCond: input='off' pattern='on' => not-matched
    add path info postfix: /var/www/html/path -> /var/www/html/path/to
    strip per-dir prefix: /var/www/html/path/to -> path/to
    applying pattern '.' to uri 'path/to'
    RewriteCond: input='off' pattern='off' => matched -->httpsでリダイレクトした筈なのに。。
    RewriteCond: input='/var/www/html/path' pattern='!-d' => matched
    RewriteCond: input='/var/www/html/path' pattern='!-f' => matched
    rewrite 'path/to' -> 'https://myhostname/path/to'
    explicitly forcing redirect with https://myhostname/path/to
    escaping https://myhostname/path/to for redirect
    redirect to https://myhostname/path/to [REDIRECT/302]
    ・
    ・
    同じのが延々と続く
    
[/code]

また、.htaccessが今ひとつ理解出来ておらず、記載が冗長な気もしており、もっとスマートな記述方法などがございましたら教えていただきたいです。  
よろしくお願いします。


CC BY-SA 3.0
2016-02-11T09:08:52.647
21975
2018-08-29T11:42:30.217
2016-02-11T10:28:04.257
8000
14368
question
aws apache
mod_rewrite HTTPアクセスをHTTPSに統一


実際に試してはいないので、ネットで調べただけですが・・・

> AWS ロードバランサー でSSL設定済み

これが原因かと思います。クライアントがELBに対してHTTPSで接続しようが、背後のインスタンスにはHTTPでリクエストが飛んできます。当然
`%{HTTPS}` は常に `off`
ですから、リダイレクトが無限に発生します。クライアントからELBへの接続がHTTPSかどうかを判別するには、ELBが付加する `X-Forwarded-
Port` や `X-Forwarded-Proto` というHTTPヘッダを利用する必要があります。

[Elastic Load Balancing の X-Forwarded ヘッダー - Elastic Load
Balancing](http://docs.aws.amazon.com/ja_jp/ElasticLoadBalancing/latest/DeveloperGuide/x-forwarded-
headers.html)

またELB自身も定期的にヘルスチェック用のリクエストを送信してきます。このリクエストには `X-Forwarded-**`
というヘッダがありませんが、リダイレクトではなく200を返す必要があります。

その他の気になる点として、

  * HTTPSへのリダイレクトはLaravelを通すURLだけでなく、実在するファイルに対しても行うべきですから、 `!-d` `!-f` といった判定はない方がよいでしょう。またパターン `.` では `http://hoge.com/` にマッチしないので、`.*` や `^` などを使う必要があります。
  * HTTPSへのリダイレクトは恒久的なものでしょうから、301リダイレクトが適切です。
  * 先にHTTPSへのリダイレクトを処理して打ち切ることで、`RewriteCond %{HTTP} off` といった判定は省略できます。

諸々をまとめると、次のような形でどうでしょうか。

[code]

    # ELBまでhttpで接続された場合はリダイレクト
    # （HealthCheckは当該ヘッダがないので偽になるはず）
    RewriteCond %{HTTP:X-Forwarded-Port} =http
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    
    # 実在するフォルダ以外は末尾の/を取り除く
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ /$1 [L,R=301]
    
    # 実在しないパスは全てLaravelで処理する
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule . index.php [L]
    
[/code]

参考 [AWS Elastic Load Balancer と Apache を使って HTTPS(SSL) 通信を行うための設定方法 -
komiyakの通り道](http://d.hatena.ne.jp/komiyak/20130807/1375845025)


CC BY-SA 3.0
2016-02-11T12:06:56.347
21982
2016-02-11T12:06:56.347
8000
21975
answer


`public`フォルダで`.htaccess`ファイルの中は以下のコードを追加してください。

[code]

    RewriteEngine On
    
    # Redirect to https
    RewriteCond %{HTTP:X-Forwarded-Proto} !https
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
    
[/code]

他の方法はウェブサーバーの設定を編集してみる。たとえば、Nginxの設定のファイルです。

[code]

    server {
     listen 80;
     server_name domain.net www.domain.net;
     rewrite ^(.*) https://domain.net$1 permanent;
    }
    
[/code]

Apacheの設定も変更することが出来ます。


CC BY-SA 4.0
2018-08-29T11:42:30.217
47917
2018-08-29T11:42:30.217
29912
21975
answer