search
LoginSignup
4

More than 1 year has passed since last update.

posted at

Railsの本番環境でなぜかセッションが保存できない問題を解決した経緯

概要

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4