質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Cookie

HTTPにおけるCookieとは、クライアントのウェブブラウザ上に保存された一時的なデータを指します。クライアント側のJavaScriptでも、サーバー側のHTTPヘッダーでもクッキーの読み書き・修正・削除が可能です。

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

セッション

Sessionはクライアントがサーバに送ったすべてのリクエストのことを指します。

ログイン

ログインは、ユーザーがコンピューターシステムにアクセスするプロセスの事を呼びます。

Q&A

解決済

1回答

2811閲覧

ローカル環境でのみ、ログインに成功してもセッションIDが付与されない。

punchan36

総合スコア105

Cookie

HTTPにおけるCookieとは、クライアントのウェブブラウザ上に保存された一時的なデータを指します。クライアント側のJavaScriptでも、サーバー側のHTTPヘッダーでもクッキーの読み書き・修正・削除が可能です。

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

セッション

Sessionはクライアントがサーバに送ったすべてのリクエストのことを指します。

ログイン

ログインは、ユーザーがコンピューターシステムにアクセスするプロセスの事を呼びます。

0グッド

1クリップ

投稿2021/08/24 06:23

編集2021/08/30 09:20

数日前に質問を投稿してから進展があり、当初記述しておりました内容とは論点(原因)が異なる事が分かりましたので、質問文全体を新しく編集し直しました。

背景

コードをいじっていないにも関わらず、実装出来ていたログイン機能が使えなくなりました。ログイン画面で正しいメールアドレス・パスワードを入力しても再度ログイン画面にリダイレクトされてしまうと言った状況です。
尚、deviseは使用しておりません。

ログイン周りのコードに問題があるのかとまず考えましたが、ログを辿るとログインが成功した際のコードに分岐されている事が分かりました。

またBurp Suiteと言う「ブラウザ - サーバー間(ローカルプロキシ)」の通信の記録を観察するツールを使用し調べてみた所、ログイン後にセッションIDがなぜか付与されておらず、結果としてauthenticate_userに引っ掛かりログインが出来なくなっている状況だと分かりました。この原因を突き止め、解決したいです。

更にngrokと言う、localhostにhogehoge.ngrok.comで外部からアクセスできるツールを使い、外部からアクセスした場合に違いが生じるかを確認した所、何とこちらではログインに成功しました。その様子を同じようにBurp Suiteで調べた所、こちらではログイン後にセッションIDが付与されている様子が確認出来ました。

つまりローカル環境でログインを試みた際にのみ、なぜかセッションIDが付与されなくなっているようなのです。
直近でコードに関して作業はしておらず、以下の作業をしておりました。

  • Gitの導入。
  • 作成した「アプリ1」を、Gitを使用しGitHubにプッシュ。
  • Sourcetreeを導入し、GitHubにプッシュ出来るよう連携。
  • GitHubの内容をSourcetreeでクローン。フォルダ名を「アプリ2」とし、Sourcetree内で連携させたいローカルのワークツリーに指定。

更に前に作業していた事はと言えば、セッションに関して以下の1行加えた事くらいです。
またこの行は現在コメントアウトしておりますが、状況は変わりません。

application.rb

config.session_store :cookie_store, expire_after: 8.hours

これらの作業が済んだ後、上記の問題が発生した次第です。

該当のソースコード

routes.rb

get "login" => "users#login_form" post "login" => "users#login" post "logout" => "users#logout"

application_controller.rb

class ApplicationController < ActionController::Base protect_from_forgery with: :null_session before_action :set_current_user skip_before_action :verify_authenticity_token caches_action :set_current_user, :authenticate_user, :forbid_login_user def set_current_user @current_user = User.find_by(id: session[:user_id]) end def authenticate_user if @current_user == nil flash[:notice] = "You need to log in" redirect_to("/login") end end def forbid_login_user if @current_user flash[:notice] = "You are already logged in" redirect_to("/") end end end

users_controller.rb

before_action :authenticate_user, {except: [:new, :create, :login_form, :login]} before_action :forbid_login_user, {only: [:new, :create, :login_form, :login]} before_action :ensure_correct_user, {only: [:edit, :update]} before_action :ensure_correct_user_account, {only: [:setting_password, :update_password, :setting_email, :update_email, :delete_account, :destroy]} caches_action :index, :show, :follow, :new, :create, :edit, :user_params, :update, :destroy, :login_form, :login, :logout, :likes, :ensure_correct_user, :followings, :followers, :top def login @user = User.find_by(email: params[:email]) if @user && @user.authenticate(params[:password]) session[:user_id] = @user.id flash[:notice] = "You have successfully logged in" redirect_to("/") else @error_message = "Email address or password is incorrect" @email = params[:email] @password = params[:password] render("users/login_form") end end def login_form end def logout session[:user_id] = nil flash[:notice] = "You have successfully logged out" redirect_to("/login") end

ログインに成功した場合はredirect_to("/")の様に、トップページに遷移するようにしています。

ログ

ログインを試みた際のログです。
Started GET "/"とある様に、ソースコード上ログインには成功しているようです。しかしその後Filter chain halted as :authenticate_user rendered or redirectedと怒られ、"/login"にリダイレクトされています。

Started POST "/login" for ::1 at 2021-08-24 14:44:31 +0900 Processing by UsersController#login as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"JBcKtTsdCT0JXgyIfzjKVqi/8KEz4pRmUXB2Kybn8eHcnz7UKXoMsbBRkBCnoUqwnIdi4hUkZ/6oQKFVqMyG/g==", "email"=>"hoge", "password"=>"[FILTERED]"} User Load (35.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1 ↳ app/controllers/application_controller.rb:9 User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`email` = 'hoge' LIMIT 1 ↳ app/controllers/users_controller.rb:255 Redirected to http://localhost:3000/ Completed 302 Found in 422ms (ActiveRecord: 41.9ms) Started GET "/" for ::1 at 2021-08-24 14:44:32 +0900 Processing by UsersController#top as HTML User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1 ↳ app/controllers/application_controller.rb:9 Redirected to http://localhost:3000/login Filter chain halted as :authenticate_user rendered or redirected Completed 302 Found in 6ms (ActiveRecord: 0.6ms) Started GET "/login" for ::1 at 2021-08-24 14:44:32 +0900 Processing by UsersController#login_form as HTML User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1 ↳ app/controllers/application_controller.rb:9 Rendering users/login_form.html.erb within layouts/application Rendered users/login_form.html.erb within layouts/application (0.9ms) CACHE User Load (0.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1 ↳ app/views/layouts/application.html.erb:51 Completed 200 OK in 244ms (Views: 233.9ms | ActiveRecord: 0.5ms)

Burp Suitでの表示

ngrokを使用し、外部からアクセスしてからログインした際の記録。
左下の「Request」内にCookieが、また右下の「Response」内にSet-cookieがそれぞれ表示されています。

ローカル環境でログインを試みた際の記録。
左下の「Request」内にCookieが、また右下の「Response」内にSet-cookieがそれぞれ出てきません。

試したこと

サーバーの再起動、パソコンの再起動を試しても状況は変わらず、
ブラウザによる違い(Google Chrome, Firefox, Braveで試しました)も関係ありませんでした。

サーバーやセッション関連に原因があるかもしれず、プログラミング関連の質問としてそぐわなくなっておりましたら申し訳ありません。どなたかご助言を頂けますと有難いです。

補足情報(FW/ツールのバージョンなど)

ruby 2.6.4p104
RubyGems 3.0.3
Rails 5.2.3
Burp Suite Community Edition 2021.8.2

追記

以下の作業を試みましたが、依然として結果は同じでした。

  • rails sをする際のポートを3000から3001に変える。
  • コマンドにてbundle exec rake tmp:cache:clearを実行。
  • コマンドにてrails tmp:clearを実行。
  • users_controller.rblogin_form内にて、以下の様にセッションの履歴を執拗に消す。
def login_form reset_session session[:user_id] = nil session.delete(:user_id) end

また外部から私のlocalhostに接続した場合はなぜか上手くいく為、直接localhostに接続した場合との違いを考えてみました。
ローカル環境から直接localhostに接続した場合は、このようにURL横がビックリマークの表示になります。
イメージ説明
一方で外部から私のlocalhostに接続した場合は鍵マークになっています。
イメージ説明
ページがSSL化されているかどうかでセッションIDが付与されないなどの違いが出てくるものなのでしょうか…。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

neko_daisuki

2021/09/03 03:35

もしセキュリティソフトを導入している場合、それらをオフにするとどうなりますか?
punchan36

2021/09/07 12:30

有難うございます。返信が遅くなり申し訳ありません、寝込んでおりました…。 「Windowsファイアウォールを無効にする」を試してみましたが結果は同じでした。 ただ、SSLが関係しているかもしれないと見当を付けました。 ngrokで外部からlocalhostに接続するに当たり、 http(s無し)で試すと、ローカル環境と同じようにログインページにリダイレクトされました(失敗)。 しかしhttps(s有り)で試すとログインは成功しました。 理由はよく分かりませんが、とにかくsが有るか無いかで結果が変わるようです。。 なぜこうなってしまったのか本当に分からないのですが、どこかをいじれば解決する問題なのでしょうか…。
neko_daisuki

2021/09/07 13:39

もしかしてセキュリティソフトが平文の通信のクッキーを削除しているのかと思ったのですが違ったようですね。 application.rb(もしくは environments/[development|production].rb) で config.session_store(:cookie_store, { secure: true }) とすると http のヘッダに Set-Cookie が含まれないことを確認しました(false では送信される)が、関係ないでしょうか。
punchan36

2021/09/07 14:01

有難うございます! application.rb、development.rb、production.rbには session_store に関する記述はなく、 config.session_store(:cookie_store, { secure: true }) をそれぞれのファイルに加えてみましたが結果は変わらずでした。念のため、記述後にはサーバーを立ち上げ直して試しております。 また特定のユーザーだけでこの不具合が起きる訳ではなく、データベースに保存されている他のユーザーで試しても同様です。新規ユーザー登録は出来ます(データベースに保存されます)が、例のごとくサインイン(ログイン)後にセッションIDがなぜか付与されないようで、やはりログイン画面にリダイレクトさせられてしまうと言った状態です…。
neko_daisuki

2021/09/07 14:26

あと僕に考え付くのは、それっぽいログもないので可能性は低いと思いますが、CSRF の null_session に引っかかったときの挙動に似てます。 ApplicationController に protect_from_forgery :except => :complete, :with => :exception として http でログインしてエラーになりませんか
punchan36

2021/09/07 14:38

有難うございます。以下の様に書き換えてみましたが、やはりダメみたいです…。 protect_from_forgery with: :null_session ↓ protect_from_forgery :except => :complete, :with => :exception authenticate_user に関するエラーが出てしまい、ログイン画面にリダイレクトでされます。 Filter chain halted as :authenticate_user rendered or redirected 機能は作り終え、サービスを公開しようと思っていた矢先にこの問題が起こってしまいました…。バックアップを取っていなかったのが痛いです。。 サイトをSSL化すれば公開しても良いのか、それとも解決するまで動けないのか…。 同じコードを使っているのにhttpsからであればエラーが発生しないと言うのが、得たいが知れず気味が悪いです。
neko_daisuki

2021/09/07 15:20

ごめんなさい、一応の確認なのですが、上のコメントに config.session_store(:cookie_store, { secure: true }) をそれぞれのファイルに加えてみました とありますが、config.session_store(:cookie_store, { secure: false }) にしないと送信されません。 また、application.rb に以下の記述が残っていたらコメントアウトしてください。 config.session_store :cookie_store, expire_after: 8.hours false で試していたらすみません。
neko_daisuki

2021/09/07 15:29

rails はログインが関係ないページでもクッキーを送信していたはずなので、 「ローカル環境でログインを試みた際の記録」の左側にCookieがないのも変ですよね。 (念のため)ブラウザのプライベートウインドウでトップページを開き、クッキーが送信されているか確認して、 送信されていないようならログインに関わらずアプリ全体でセッションの機能がおかしくなってそうです。 返信よりも体調の方を優先してくださいませ。
neko_daisuki

2021/09/07 15:34

続けてすみません。もしかするとこれが原因かも・・・ 「なおChrome 80以降でSecure属性を付けずSameSite=Noneを指定した場合、set-cookie自体が無効になります。」 http://www.osscons.jp/jov9t04kz-537/ 以下をお試しください。 config.session_store(:cookie_store, { secure: Rails.env.production?, same_site: :lax })
punchan36

2021/09/08 09:08

有難うございます! アドバイスを頂いた順に試してみました。 ①まず secure: true を false に変えて試す点ですが、こちらも結果は変わりませんでした。尚、application.rb内の以下の記述はコメントアウトしております。 config.session_store :cookie_store, expire_after: 8.hours サーバーを立ち上げて、ログイン画面を表示させた際に出たログにセッション関連の内容がありましたが、これは通常の場合でも出るログですよね…。 Started GET "/login" for ::1 at 2021-09-08 16:56:43 +0900 (50.1ms) SET NAMES utf8mb4, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483 ②Firefoxのプライベートウインドウでトップページ(http://localhost:3000/login)を開いてみた所、Cookie: _アプリ名_session=*******の箇所にてクッキーの送信が確認出来ませんでした…。 こちらも、プライベートウインドウにて外部からhttpsでアクセスした場合はなぜかクッキーがしっかりと付与されています。ログイン前後に関わらず、localhostで表示した場合はこの辺りが全ておかしくなるようです…。 ③application.rb、development.rb、production.rbのそれぞれに以下の記述を加えましたが、ダメでした。 config.session_store(:cookie_store, { secure: Rails.env.production?, same_site: :lax }) ブラウザに関係なくおかしくなるなど症状も酷似していたので、個人的にはこれで直って欲しかったのですが…。 因みにGoogle Chrome は最新版で、バージョンは 93.0.4577.63(Official Build) (64 ビット)です。 新しいバージョンですので、頂いたリンクから見れますQiita記事の中にある「Enabledに変更する」箇所は見当たりませんでした。 https://qiita.com/ahera/items/0c8276da6b0bed2b580c#%E3%83%86%E3%82%B9%E3%83%88%E6%96%B9%E6%B3%95 お気遣いまでして頂き、本当に有難うございます! ③関連でもう一息何か出来る事は無いかと、今調べている所です。
neko_daisuki

2021/09/08 13:01

お疲れ様です。他に出来そうなことは ・http://lvh.me:3000 でクッキーが送信されているか確認する ・rails new して新しいプロジェクトを作りhttpでクッキーが送信されているか確認して、アプリの問題かサーバーの問題か切り分ける くらいでしょうか・・・
punchan36

2021/09/09 01:31

有難うございます。 ①http://lvh.me:3000 でもクッキーは送信されていませんでした。 ②別のアプリでは、クッキーが送信されておりました…。 以前作った「sample_app」と言う空のアプリで、「http://localhost:3000/home/top」と言うルーティングのみ作っており、そちらにアクセスすると「Cookie: _sample_app_session=****」、「Set-Cookie: _sample_app_session=****」とクッキーが送信されておりました。 ですので今開発中のアプリに問題があるようです…。 原因がどうしても分からないとなると、rails newで新たに空のアプリを作り、そこに今開発中のアプリで作ったビュー、コントローラ、モデルなど、作った物を全てコピペする、と言う方法も有りなのでしょうか? こんなケースは初めてですので、表面上だけ複製して上手く動くのかは微妙な気がしますが…。
punchan36

2021/09/09 02:24

今無事解決致しました! config > initializers 内に「session_store.rb」と言うファイルを以前自分で作ってしまったのが原因だったようです…。セッションに関する内容を記述しておりました。 app_name = "アプリ名" Rails.application.config.session_store :cookie_store, key: "_アプリ名_session", expire_after: 8.hours, secure: true 以前セッションについて自分でカスタマイズ出来ないかと考えてたことがあり(セッションはRailsのデフォルトでは1日で切れるようですが、それを8時間に設定したかった)、これを「session_store.rb」と言うファイル内で編集できると知りました。しかしどうやらRails5以降ではこのファイルがデフォルトで生成されないようでしたので、どうやって編集出来るのかを模索していた所、恐らくこちらの様なページを参考にし、ファイルを自分で作成したのでした。 https://teratail.com/questions/239249 勝手にこの作業をしていた事を忘れておりました…。回答者さまが想像できない部分だったと思います。申し訳ありません。 過去に作ったアプリとフォルダ内を見比べて、異なるファイルを探す事で発見に結びつきました。有難うございます! 「session_store.rb」の中身をコメントアウトする事で解決したのですが、ただなぜ localhost ではセッションが渡されず、 https だと問題がなかったのか、そこがいまいち分かりません。。
neko_daisuki

2021/09/09 05:11

application.rb での設定が session_store.rb で上書きされてたんですね。 それで secure: true になり、http ではクッキーが送信されなかったんだと思います。 (secure: true にすると https でしかクッキーが送信されない) いま知ったのですが、bin/rails c して、Rails.application.config.session_options すれば 現在のセッションの設定を確認できるみたいです。
punchan36

2021/09/09 08:14

本当に有難うございました! 以前新規作成していた session_store.rb は削除し、 application.rb にて一旦今回は以下を記述する事に致しました。 config.session_store :cookie_store, expire_after: 8.hours サーバーを起動し直しても問題なく動きましたし、rails c でセッションの内容も確認出来ました。 尚記述に関してですが、本番環境でのみsecure: trueにする記述も加えた方が好ましいでしょうか? 今後はこまめにコミットし、バックアップを取っていこうと思います。 ベストアンサーにさせて頂きたいですので、ご回答もお願い出来ませんでしょうか?
guest

回答1

0

ベストアンサー

ruby

1config.session_store :cookie_store, secure: true

secure が true に設定されていると、https のみクッキーを送信するようになります。
デフォルトは false です。

本番環境のみ secure を true にするには以下のようにします。
https のみで運用するならそう設定するのが好ましいでしょう。

ruby

1config.session_store :cookie_store, secure: Rails.env.production?

以下のコードで現在の設定を確認することができます。

ruby

1Rails.application.config.session_options

投稿2021/09/09 13:30

neko_daisuki

総合スコア2090

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

punchan36

2021/09/09 14:35

重ね重ね有難うございます! セッションの有効期限も含めた形で、一先ず以下の様に記述致しました。 config.session_store :cookie_store, expire_after: 8.hours, secure: Rails.env.production? secure属性についてはもう少し学んで、確実に必要そうであれば本番環境でオンにしたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問