如何使用React在Rails中设置极简主义身份验证?

时间:2017-12-26 18:17:01

标签: reactjs session authentication cookies ruby-on-rails-5

我正在尝试在我的Rails后端和我的React前端之间建立一个最小的身份验证层,但我遇到了一些问题。

  1. 我似乎无法找到服务器传递给我的客户端的cookie密钥值。在网络标签中,我在回复中看到了Set-Cookie:_skillcoop_session=....,但当我使用js-cookie查找上述Cookie _skillcoop_session时,我只看到一个名为identity-token=...的Cookie它的值与_skillcoop_session不同。如何在浏览器中访问_skillcoop_session

  2. 我将哪个标题密钥传递给服务器,以便向我的后端发出信号以使用'这个'标题键与其存储的会话相匹配?在this post中,Justin Weiss似乎建议我使用以下标题向服务器发出请求:Cookie: _skillcoop_session=....

  3. 我这样做是错的吗?我会更好地使用像devise这样的宝石吗?

  4. 另外,为了在我的其他控制器中加载会话,我必须做session['init'] = true之类的事情,并且我从这个SO post学会了这样做。这看起来很丑陋。在我之前在不同的请求中将其设置为不同的控制器操作之后,为什么我必须在单独的控制器操作中手动重新加载会话?

  5. 我目前只是截断用户和身份验证 - 我想要做的就是设置session[:user_id]并且能够在其他控制器操作中读取该会话数据。为此,我需要考虑两个主要文件:UsersControllerTransport.js。在UsersController中,我只是将session[:user_id]与数字1对齐,而在Transport.js中,我希望传递从服务器收到的Cookie,以便后端可以保持之间的会话请求与客户。

    这是我的控制器:

    class UsersController < ApplicationController
    
      def create
        session[:user_id] = 1
        render json: user_stub, status: :ok
      end
    
      def show
        puts "user id: #{session[:user_id]}"
        # should return, 1, but is returning, nil...why?
        render json: user_stub, status: :ok
      end
    
      private
    
      def user_stub
        {
          id: 1,
          email: params['email'] || 'fakeemail@gmail.com',
          password: params['password'] || 'fake password'
        }
      end
    end
    

    这是我的应用程序的主要位置,我向服务器发出请求 - 它是一个抽象我称之为Transport.js:

    require('es6-promise').polyfill();
    require('isomorphic-fetch');
    var cookie = require('js-cookie');
    
    
    const GET = 'GET';
    const POST = 'POST';
    
    function Transport() {
    }
    
    Transport.prototype.get = function(url, options = {}) {
      return this.query(GET, url, null, options);
    };
    
    Transport.prototype.post = function(url, dataString, options = {}) {
      return this.query(POST, url, dataString, options);
    };
    
    Transport.prototype.query = function(method, url, dataString, options = {}) {
      var data;
    
      if (dataString) {
        data = JSON.parse(dataString);
      }
    
      switch(method) {
        case GET:
          return fetch(url, Object.assign({headers: {'Cookie': cookie.get('_skillcoop_session')}}, options, {
            method: method
          }));
        case POST:
          return fetch(url, Object.assign({
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(data)
          }, options, {
            method: method
          }));
        default:
          throw new Error("This HTTP Method is not supported.");
      }
    };
    
    module.exports = Transport;
    

1 个答案:

答案 0 :(得分:1)

  1. 根据此SO post,无法访问JS中的Set-Cookie标头。因此,我想我在响应标题中处理Set-Cookie的尝试是一种愚蠢的努力。

  2. According to我用来发出HTTP请求的NPM包,我需要将第二个参数中的{credentials: 'same-origin'}键值对传递给fetch,这将是'自动发送当前域的cookie'。这样做了 - 会话对象可用,并包含在前一个请求中以不同操作在会话中设置的user_id

  3. 是。我改变了我如何解决这个问题。我非常倾向于Reddit post。简而言之,我在后端使用ruby-jwt并将令牌存储在前端的localStorage中。每个请求到服务器的请求都会在标头AUTHORIZATION中包含令牌。

  4. 在以下步骤1和2中,看起来我不再需要“重新加载会话”。