#概要
railsで本番環境にプッシュしたアプリがある日セッションを使った機能の全てが動作しなくなるという絶望的な問題にぶち当たった。めちゃくちゃ苦戦したし記事も全然なかったのでその解決方法を記しておく。
最終的にこの記事から設定しなおして解決しました。
https://www.cotegg.com/blog/?p=1850
#環境
・EC2にデプロイ
・サーバー環境はWebサーバーにnginx、アプリケーションサーバーにPuma
・AWSのELBにACMのSSL証明書をアタッチしてSSL化↓
クライアント→ELB→nginx→puma
#セッションが保存されない原因
####まず、セッションが保存されない原因
RailsではCSRF(クロスサイトリクエストフォージェリー)という脆弱性からサイトを守るための対策として
protect_from_forgeryというメソッドでサイトを保護している
application.html.erb
のheadタグ内にcsrf_meta_tag
という記述をしているが
ここで認証用のauthenticate_tokenを生成しておりこの値を使ってサイトを認証している。
この辺りの説明は腐る程ググれば出てくるため割愛。
このprotect_from_forgeryメソッドのデフォルトの設定でこのauthenticate_tokenが正しくないと
セッションを空にする。(:null_session
オプション)が指定されている。
こいつのせいでセッションは空になっている。
※これが原因かどうか一発でわかる方法として、application_controller.rb
に
protect_from_forgery with: :exception
←CSRFトークンが正しくなければエラーを返す
を記述してサイトにアクセスする
ActionController::InvalidAuthenticityToken
というエラーが出たら原因はそれ
つまりなんらかの原因でCSRFの認証が通っていない
#なぜこんなエラーがでるのか
冒頭に環境を載せておいたが
クライアント→ELB→nginx→puma
という経路でアプリケーションにアクセスするようになっている
ELBにはSSL証明書をアタッチしてあり、自分のこの構成だと
ELBまではhttpsアクセス
ELBとnginxはhttpアクセスになっている。
実際にユーザーがアクセスするのはhttpsなのにrailsアプリ側にはhttpでアクセスしていると
情報が伝わってしまい、ここで矛盾が生じるためクロスサイト認定され
エラーが起きてしまっている模様。
対策は
nginxなら
/etc/nginx/nginx.confに
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #これ追加
proxy_set_header X-Forwarded-Proto https; #これ追加
proxy_pass http://www.xxxx.com;
}
としてやるとアクセスするURLと伝わるヘッダー情報が一致してエラーが出なくなる
つまり解決
#補足
自分なりの理解で対処した問題の内容をまとめただけのため
間違いがあればご指摘いただけますと幸いです。
Twitterアカウント↓
https://twitter.com/TakeWeb1