Не удается сохранить сеанс при обновлении страницы - PullRequest
1 голос
/ 16 октября 2019

У меня есть приложение, созданное с помощью Rails, React и Webpacker. Я использую аутентификацию на основе токенов, поэтому, когда пользователь создает учетную запись или выполняет вход, ему назначается токен в БД. Этот токен затем используется для доступа к профилю пользователя. Страница профиля загружается без проблем после аутентификации пользователя, но я получаю сообщение об ошибке Rails, говорящее Couldn't find Registration, и затем оно ссылается на эту строку из моего registration_controller: registration = Registration.find_by_auth_token!(request.headers[:token]).

Я попытался установить токен в localStorage, когда он получен из бэкэнда, и я попытался вызвать токен из localStorage, когда страница загружается на компоненты верхнего уровня, используя хук useEffect, но этоне похоже, что мое приложение React даже начинает рендериться, пока я не получил эту страницу с ошибкой. Ни одно из утверждений Console.log, которые я добавил в свое приложение React, не появляется в консоли, когда я получаю эту ошибку.

registration_controller.rb

class RegistrationController < ApplicationController
  skip_before_action :verify_authenticity_token

  def index; end

  def custom
    user = Registration.create!(registration_params)
    render json: { token: user.auth_token, id: user.id }
  end

  def profile

    registration = Registration.find_by_auth_token!(request.headers[:token])
    render json: {
      registration: { username: registration.username, email: registration.email, name: registration.name }
    }
  end

  private

  def registration_params
    params.require(:registration).permit(:username, :email, :password, :name)
  end
end

auth.js (действия)

import axios from 'axios';
import reduxStore from '../reduxStore';

export const LOGOUT_START = 'auth/logoutStart';
export const LOGOUT_SUCCESSFUL = 'auth/logoutSuccessful';
export const LOGOUT_ERROR = 'auth/logoutError';
export const LOGIN_START = 'auth/loginStart';
export const LOGIN_SUCCESSFUL = 'auth/loginSuccessful';
export const LOGIN_FAILURE = 'auth/loginFailure';
export const REGISTRATION_START = 'auth/registrationStart';
export const REGISTRATION_SUCCESSFUL = 'auth/registrationSuccessful';
export const REGISTRATION_FAILURE = 'auth/registrationFailure';

export const logout = () => (dispatch) => {
  const headers = { token: localStorage.token };
  // console.log('redux store', reduxStore().getState())
  // console.log('NEW local storage', localStorage);
  dispatch({ type: LOGOUT_START });

  try {
    axios.delete('/logout', { headers })
      .then((res) => {
        dispatch({
          type: LOGOUT_SUCCESSFUL,
          payload: res.data,
        });
      });
  } catch (e) {
    console.error(`logout error: ${e}`);
    dispatch({
      type: LOGOUT_ERROR,
      payload: e,
    });
  }
};

export const login = ({ username, password }) => (dispatch) => {
  const headers = {
    'Content-Type': 'application/json',
  };

  const data = {
    username,
    password,
  };

  dispatch({ type: LOGIN_START });

  try {
    axios.post('/login', data, { headers })
      .then((res) => {
        localStorage.setItem('token', res.data.token);
        dispatch({
          type: LOGIN_SUCCESSFUL,
          payload: res.data,
        });
        // localStorage.setItem('myValueInLocalStorage', event.target.value)
        console.log('localStorage', localStorage);
      });
  } catch (e) {
    console.error(`login error ${e}`);
    dispatch({
      type: LOGIN_FAILURE,
      payload: e,
    });
  }
};

export const createUser = ({
  username,
  password,
  name,
  email,
}) => (dispatch) => {
  const headers = {
    'Content-Type': 'application/json',
  };

  const data = {
    registration: {
      username,
      password,
      name,
      email,
    },
  };

  dispatch({ type: REGISTRATION_START });

  try {
    axios.post('/registration/custom', data, { headers })
      .then((res) => {
        dispatch({
          type: REGISTRATION_SUCCESSFUL,
          payload: res.data,
        });
      });
  } catch (e) {
    console.error(`createUser error: ${e}`);
    dispatch({
      type: REGISTRATION_FAILURE,
      payload: e,
    });
  }
};

Я ожидаю, что этот токен будет всегда доступен из заголовков объекта Request на стороне Rails, поэтому страница профиля может отображаться, когда пользователь обновляет окно.

Ответы [ 2 ]

0 голосов
/ 19 октября 2019

Мне удалось это исправить, добавив некоторые вспомогательные функции и изменив логику на стороне React. Я начал устанавливать / получать / очищать токен в localStorage, когда страница загружается, когда пользователь входит в систему и когда пользователь выходит из системы, и это в итоге стало лучшим способом управления состоянием с проверкой подлинности во внешнем интерфейсе

0 голосов
/ 16 октября 2019

Если ваш заголовок "token", rails преобразует его в "HTTP_TOKEN", запустит puts request.headers.inspect, чтобы увидеть, что на самом деле внутри этого объекта заголовков, я думаю, что вы должны использовать строку, а не символ (headers ['HTTP_TOKEN '] вместо заголовков [: http_token])

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...