ELB+Nginxの構成でHTTPSアクセスをする場合は、以下の様にELBでHTTPSで受けて、その後ろはHTTPでリクエストするという方法がよく採用されると思う。
client
↓ (HTTPS)
ELB
↓ (HTTP)
nginx
↓ (HTTP)
Rails
この時、Railsではどうやって大元のリクエストがHTTPSであることを判定できるかについての解説。
RailsでのHTTPSアクセスを判定する方法
request.ssl? メソッドで判定できる。
request.ssl?
request.ssl?の実装はどうなってるか
HTTPヘッダー等を見て具体的にこのような判定をしている。
def scheme
if @env['HTTPS'] == 'on'
'https'
elsif @env['HTTP_X_FORWARDED_SSL'] == 'on'
'https'
elsif @env['HTTP_X_FORWARDED_SCHEME']
@env['HTTP_X_FORWARDED_SCHEME']
elsif @env['HTTP_X_FORWARDED_PROTO']
@env['HTTP_X_FORWARDED_PROTO'].split(',')[0]
else
@env["rack.url_scheme"]
end
end
def ssl?
scheme == 'https'
end
schemeメソッドで「https」が返されれば、https判定されることになる。
今回の構成のような例では、「url_scheme」はhttpになるため、その他のヘッダー項目での判断が必要となる。
では、フロントがELB+Nginxの場合、Railsにはどのようなヘッダが渡されるか?
ELBからNginxへ渡されるリクエストヘッダー
ELBでは以下のHTTPヘッダを付与して、Nginxへ渡してくれる。
- X-Forwarded-For :クライアントのIPアドレス
- X-Forwarded-Port :クライアントの接続ポート ( 80 / 443)
- X-Forwarded-Proto:クライアントの接続プロトコル ( http / https)
httpsアクセスの場合は、「X-Forwarded-Proto」にhttpsが設定されているので、
nginxでは特別な設定はせず、これをRailsに受け流してあげれば、request.ssl?にてhttps判定が行われる。