【问题标题】:Cannot Maintain Session on Page Refresh无法在页面刷新时保持会话
【发布时间】:2020-02-12 18:06:05
【问题描述】:

我有一个使用 Rails、React 和 Webpacker 构建的应用程序。我正在使用基于令牌的身份验证,因此当用户创建帐户或登录时,他们会在数据库中分配一个令牌。然后使用此令牌访问用户的个人资料。用户身份验证后,配置文件页面加载没有问题,但我收到一个 Rails 错误说Couldn't find Registration,然后它从我的registration_controller 引用此行:registration = Registration.find_by_auth_token!(request.headers[:token])

当从后端接收到令牌时,我尝试在 localStorage 中设置令牌,并且当页面使用useEffect 钩子在顶级组件上加载时,我尝试从 localStorage 调用令牌,但它没有在我收到此错误页面之前,我的 React 应用程序似乎甚至开始呈现。当我收到此错误时,我添加到我的 React 应用程序中的任何 Console.log 语句都不会出现在控制台中。

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,
    });
  }
};

我希望这个令牌始终可以从 Rails 端的 Request 对象中的 Headers 中获得,以便在用户刷新窗口时可以显示配置文件页面。

【问题讨论】:

    标签: ruby-on-rails reactjs webpack redux


    【解决方案1】:

    如果您的标头是“令牌”,rails 会将其转换为“HTTP_TOKEN”,运行 puts request.headers.inspect 以查看该标头对象中的实际内容,我认为您必须使用字符串而不是符号(标头 [' HTTP_TOKEN'] 而不是 headers[:http_token])

    【讨论】:

    • 我检查了这个,但在 request.headers 对象中没有看到 HTTP_TOKEN。我觉得问题可能是令牌是在 Redux 请求中发送的,但是 Rails 在 Rails/React 之前加载,因此带有令牌的请求永远不会从 React 发送到 Rails?
    • 你有这个在网络服务器上在线运行吗?如果是这样,默认情况下,nginx 期望自定义标头称为“X-Something”。我不明白你的意思是请求没有发送,你可以查看浏览器的开发工具和rails服务器的日志来确认发送和接收。
    • 这没有部署,它在本地运行。我的意思是 Rails 控制器方法在 React 应用程序加载之前被击中,所以它没有收到令牌头。如果 Rails 在点击控制器方法之前等待 React 加载,React 将能够将令牌发送到 Rails 以供该方法使用并加载适当的用户。
    【解决方案2】:

    我可以通过添加一些辅助函数和更改 React 端的一些逻辑来解决这个问题。当页面加载、用户登录和用户退出时,我开始在 localStorage 中设置/获取/清除令牌,这最终成为管理前端身份验证状态的更好方法

    【讨论】:

      猜你喜欢
      • 2022-11-27
      • 1970-01-01
      • 1970-01-01
      • 2019-02-25
      • 2017-07-26
      • 2019-12-08
      • 1970-01-01
      • 1970-01-01
      • 2012-08-01
      相关资源
      最近更新 更多