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

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

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

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

Ruby on Rails 5

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

セッション

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

ログイン

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

解決済

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

punchan36
punchan36

総合スコア96

Cookie

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

Ruby on Rails 5

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

セッション

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

ログイン

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

1回答

0評価

1クリップ

653閲覧

投稿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が付与されないなどの違いが出てくるものなのでしょうか…。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

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にする記述も加えた方が好ましいでしょうか? 今後はこまめにコミットし、バックアップを取っていこうと思います。 ベストアンサーにさせて頂きたいですので、ご回答もお願い出来ませんでしょうか?

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Cookie

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

Ruby on Rails 5

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

セッション

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

ログイン

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