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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby on Rails 6

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

ログイン

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

11073閲覧

session[:user_id]がnilになってしまう

kiyomasa

総合スコア40

Ruby on Rails 6

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

ログイン

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

1クリップ

投稿2021/06/25 00:46

編集2021/06/29 22:43

##やりたいこと
現在バックエンドをrails -apiモード、フロントはreactでポートフォリオ を作成中です。
ログイン後に、再度ログインを保持する(current_userを確認する)機能を作成したいと思ってます。

しかし、logged_in?のメソッドを実行した時に、
session[:user_id]がnilになってしまい、うまく@current_userに代入できません。
(ログイン時にはsession[:user_id]がしっかり入るのですが、logged_in?の時に消えてしまう。)

なぜsession[:user_id]がnilになってしまうのでしょうか?
(cookieは同じ値で飛んでいる気がします)

##試したこと

binding.pryで以下のことを確認

applicationController

1def current_user 2 if session[:user_id] 3 @current_user ||= User.find_by(id: session[:user_id]) 4 end 5 binding.pry←ここにセット 6 end

irb

1[2] pry(#<Api::V1::SessionsController>)> session[:user_id] 2=> nil 3[3] pry(#<Api::V1::SessionsController>)> @current_user 4=> nil

##6/30追記
デバックツールで確認したところsessions_controller.application_controller共にメソッド自体は機能している模様ですが、
session[:user_id]はnilのままです。

cookieも同じ値が行っているのですが、sessionがうまくいきません。

##関連コード

sessionscontorller

1 2 3module Api 4 module V1 5 class SessionsController < ApplicationController 6 before_action :current_user, only: [:logged_in?] 7 8#loginでurl飛んできた後に実行するメソッド 9 def create 10 @user = User.find_by(email: session_params[:email]) 11 12 if @user && @user.authenticate(session_params[:password]) 13 login @user 14 render json: { 15 logged_in: true, 16 user: @user } 17 else 18 render json: { status: 401, errors: ['正しいメールアドレス・パスワードを入力して下さい' ] ,user: @user ,session:session{user_id}} 19 end 20 end 21 22#logged_inでurl飛んできた後に実行するメソッド 23 def logged_in? 24 if @current_user 25 render json: { logged_in: true, user: @current_user } 26 else 27 render json: { logged_in: false, errors: 'ユーザーが存在しません,ログインし直して下さい' } 28 end 29 end 30 31 private 32 33 def session_params 34 params.require(:user).permit(:email, :password) 35 end 36 end 37 end 38end

Applicationcontroller

1 2class ApplicationController < ActionController::API 3 include ActionController::Helpers 4 before_action :fake_load 5 skip_before_action :verify_authenticity_token, raise: false 6 # Railsが認証トークンを使用しないように 7 8 helper_method :login, :current_user 9 10 def login(user) 11 session[:user_id] = user.id 12 end 13 14 15 def current_user 16 if session[:user_id] 17 # @current_user ||= User.find(id: session[:user_id]) 18 @current_user ||= User.find(session[:user_id]) 19 end 20 end 21end

routes

1 2Rails.application.routes.draw do 3 namespace :api do 4 namespace :v1 do 5 root 'static_pages#home' 6 post '/signup', to: 'users#create' 7 8 post '/login',to:'sessions#create' 9 get '/logged_in', to: 'sessions#logged_in?' 10 delete '/logout',to:'sessions#logout' 11 12 resources :users 13 resources :recipes 14 15 end 16 end 17end

お手数ですが、どうすればsession[user_id]を取り出して@current_userにログイン中のuserを格納し、フロントへ返せるか教えていただけると幸いです。

##参考にしたサイト
https://qiita.com/kurawo___D/items/d5257e69bcb300908687#user%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E4%BD%9C%E6%88%90%E3%81%A8bcrypt%E3%81%AE%E8%A8%AD%E5%AE%9A

https://railsguides.jp/action_controller_overview.html#%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3

##環境
・ローカル環境
・ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
・Rails 6.1.3.1

###前回の質問

https://teratail.com/questions/345569

##追加のコード

フロントエンド ログイン部のuseAuth

/* eslint-disable react-hooks/exhaustive-deps */ import { useCallback, useState } from "react"; import axios from "axios"; import { useHistory } from "react-router-dom"; import { useMessage } from "./useMessege"; import { useLoginUser } from "./useLoginUser" import { loginURL } from '../urls/index' export const useAuth = () => { const history = useHistory(); const { showMessage } = useMessage(); const { setLoginUser } = useLoginUser(); const [loading, setLoading] = useState(false); const login = useCallback((data) => { setLoading(true); //ローディングアイコンをtrueに axios.post(loginURL, { user: { email: data.email, password: data.password, } }, { withCredentials: true } ).then(response => { if (response.data.logged_in) { // contextにログインユーザーの情報を保存 setLoginUser(response.data) // handleSuccessfulAuth(response.data); showMessage({ title: "ログインしました", status: "success" }); history.push("/mypage"); // apiを叩き成功したらメソッドが起動し、data(userのデータ)をmypageに渡してページ遷移する } // 認証できなかった時のエラー else if (response.data.status === 401) { showMessage({ title: `${response.data.errors}`, status: "error" }); } // うまくpostできなかった時のエラー }).catch((e) => { showMessage({ title: "認証できませんでした。再度リロードなどを行いやり直して下さい", status: "error" }); setLoading(false); }) }, [history, showMessage, setLoginUser]); return { login, loading }; };

ログインをチェックするuseAuthCheck

/* eslint-disable react-hooks/exhaustive-deps */ import { useCallback } from "react" import axios from "axios"; import { useHistory } from "react-router-dom"; import { useMessage } from "./useMessege"; import { useLoginUser } from "./useLoginUser" import { logged_inURL } from '../urls/index' export const useAuthCheck = () => { const { setLoginUser } = useLoginUser(); const history = useHistory(); const { showMessage } = useMessage(); const CheckAuth = useCallback(() => { axios .get(logged_inURL,{ withCredentials: true }) .then(response => { if (response.data.logged_in === true) { setLoginUser(response.data.user) } // 認証できなかった時のエラー else if (response.data.logged_in === false) { showMessage({ title: `${response.data.errors}`, status: "error" }); history.push("/login"); console.log(response.data.session) console.log(response.data.user) } // うまくpostできなかった時のエラー }).catch((e) => { showMessage({ title: "再度送信して下さい", status: "error" }); }) }, []); return { CheckAuth }; }

loginメソッド実行のブラウザのネットワーク
イメージ説明

logged_inメソッド実行のブラウザのネットワーク部
イメージ説明

sessions_store.rbでフロントエンドのドメインを変更し、cookieの保持は可能になりました。

if Rails.env === 'production' Rails.application.config.session_store :cookie_store, key: '_cooklog', domain: 'localhost3001' else Rails.application.config.session_store :cookie_store, key: '_cooklog' end

イメージ説明

イメージ説明
※同一cookie

cors.rb

Rails.application.config.middleware.insert_before 0, Rack::Cors do # ローカル環境 allow do origins "http://localhost:3001" resource "*", headers: :any, methods: [:get, :post, :put, :patch, :delete, :options, :head], credentials: true end end

ひたすらに詰まっております、、、わかる方がいらっしゃればご回答いただけると嬉しいです。。

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

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

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

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

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

deo_deo

2021/06/25 01:30

ログイン後にフロントエンド側できちんとログイン後のヘッダーからトークンを保持していますか? APIはステートレスなので、ログイン後にトークンがリクエストheaderに入っていないと誰からのリクエストか判断できません。 フロントエンドのAPI通信部分のコードを見せていただけるとさらに回答できるかと思います。
kiyomasa

2021/06/25 04:13

ありがとうございます。 ステートレスの理解が未熟ですみません。 useAuth部分のコードを追加させていただきました。 よろしくお願いします。。。
deo_deo

2021/06/27 00:07

回答遅くなりました。すいません。 参考にされたサイトを拝見しました。 おそらくCookieが原因だと思います。 logged_inのリクエストヘッダーにCookieが見当たりません。 参考サイトのコメント欄にも同じ方がいらっしゃるようですので一度ご確認されてみては? おそらくそれで解決すると思います。
kiyomasa

2021/06/27 01:12

お調べいただきありがとうございます。。。 確かに、コメントを参照したところ同じ方がいらっしゃったようで、私の方でもsessions_store.rbを確認したところフロントエンドのドメインが間違っていた(localhost3000→3001へ)ので修正したところ、 cookieの保持が確認できました。ありがとうございます。 ただ、session[:user_id]のところはnilのままでして、やりたいことがまだ実現できていない状態です。。。 ヘルパーメソッドがうまく動いていないのか、もう少し確認したいと思います。
guest

回答1

0

自己解決

やはりcookieが原因のようでした。(散々詰まって調べました)

元々rails をapiモードで作成しており、こちらのサイトを参考に修正をかけました。

https://daido.hatenablog.jp/entry/2020/05/06/143145

config/application.rb config.api_only = true # config.api_only = false falseにするだけでも可能でした # Added middleware manually. config.middleware.use ActionDispatch::Cookies config.middleware.use ActionDispatch::Session::CookieStore config.middleware.use

おそらくapiモードのrailsはsessionが有効でないようです。
知りませんでした。以後気をつけます。

ありがとうございました。

投稿2021/06/30 22:36

kiyomasa

総合スコア40

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問