【问题标题】:What is the best way to user authentication with Devise 3 and Backbone?使用 Devise 3 和 Backbone 进行用户身份验证的最佳方式是什么?
【发布时间】:2014-01-31 15:36:59
【问题描述】:

我正在使用这个堆栈:

  • 核心 API RESTful 与 Rails 4 和 Devise 3.2
  • 另一个带有 Backbone 的应用程序/stance

我已经阅读了很多文章、手册、stackoverflow 主题、google 随机结果、博客等,但都非常不推荐使用。

使用实用的方法(tl;dr here) 我只需要在不同的服务器状态下在 Devise 3 和 Backbone 之间进行一个真正的会话并保持它,就像两个单独的项目一样。远程登录,你懂的。

我真的很坚持,所以我非常感谢你的建议。

谢谢你们。

【问题讨论】:

    标签: backbone.js login devise ruby-on-rails-4


    【解决方案1】:

    我个人在我的项目中也遇到了同样的情况,使用 Angular 而不是 Backbone 作为前端,Rails 4 API 使用 Devise。假设我的问题是正确的,我将尝试为您总结一下。

    要在您的场景中正确使用会话,您需要确保:

    • 浏览器正确处理通信(即它们不会因为请求不符合 CORS 政策而弄乱您的数据)
    • 而且,您的请求可以通过 Rails CSRF 保护

    请阅读this article about CORS。如果您不熟悉 CORS,这篇文章应该为我的回答提供必要的背景。有关 CSRF 保护的一些信息是here

    这是您的场景分步说明:

    1. Backbone.js 发送GET 请求如http://yourserver/signin
    2. Rails Server 发送将存储在浏览器中的会话 cookie 和 CSRF 令牌,这些令牌可以存储在您的 Backbone 应用程序中的某个位置。
    3. Backbone.js 发送POST 请求,其中包含用户凭据(名称、密码)和标头中的 CSRF 令牌以及 cookie 中的当前未经授权的会话。请求包含会话信息至关重要。否则,它将在 Rails 端获得不同的 CSRF 令牌,您将收到 WARNING: Can't verify CSRF token authenticity 消息。
    4. 如果凭据正确,Backbone.js 会返回授权会话。

    以下是让它工作的方法:

    1. Rails 后端应正确响应来自前端的请求。这意味着它应该:

      • 响应OPTIONS 请求(预检请求)
      • 发送正确的 CORS 标头
      • 能够与前端通信 CSRF 令牌
    2. 前端应该:

      • 能够使用凭据发送请求
      • 获取并使用正确的 CSRF 令牌

    教 Rails 后端响应 CORS 请求的最简单方法是使用 rack-cors宝石。这也将提供正确的 CORS 标头。

    config.middleware.insert_before Warden::Manager, Rack::Cors do
      allow do
        origins '*' # it's highly recommended to specify the correct origin
        resource '*', 
            :headers => :any, 
            :methods => [:get, :post, :options], # 'options' is really important 
                                                # for preflight requests
            :expose  => ['X-CSRF-Token']   #allows usage of token on the front-end
      end
    end
    

    后端的最后一件事是提供 CSRF 令牌。自定义设计控制器应该可以完美地处理这个任务。

    class SessionsController < Devise::SessionsController
    
        after_action :set_csrf_header, only: [:new, :create, :destroy]
    
        #...
    
        protected
    
        def set_csrf_header
          response.headers['X-CSRF-Token'] = form_authenticity_token
        end
    end
    

    请注意,当您首次发送 GET 请求 (new)、通过 POST 请求 (create) 提交凭据以及通过发送 DELETE 退出应用程序时,您需要 CSRF 令牌请求(destroy)。如果您在退出时不发送 CSRF 令牌,您将无法在不重新加载页面的情况下登录。

    在 config/routes.rb 中的某处不要忘记指定您现在正在使用自定义控制器:

    /config/routes.rb
      devise_for :users, :controllers => {:sessions => "sessions"}
    

    现在,到前端。请查看this script,它覆盖标准Backbone.sync 并处理与Rails 服务器的通信。 它几乎是好的,需要进行一些更正:

      beforeSend: function( xhr ) {
        if (!options.noCSRF) {
          // we dont have csrf-token in the document anymore  
          //var token = $('meta[name="csrf-token"]').attr('content');
    
          // New Line #1
          // we will get CSRF token from your application.
          // See below for how it gets there.
          var token = YourAppName.csrfToken;
    
          if (token) xhr.setRequestHeader('X-CSRF-Token', token);  
    
          // New Line #2
          // this will include session information in the requests
          xhr.withCredentials = true;
        }
    
      //..some code omitted
      //................
    
      // Trigger the sync end event
      var complete = options.complete;
      params.complete = function(jqXHR, textStatus) {
         // New Lines #3,4
         // If response includes CSRF token we need to remember it
         var token = jqXHR.getResponseHeader('X-CSRF-Token') 
         if (token) YourAppName.csrfToken = token;
    
         model.trigger('sync:end');
         if (complete) complete(jqXHR, textStatus);
      };
     }
    

    我不确定这是否可以作为对您问题的完整答案,但至少可以从它开始。这可能不是最好的方法,但它就是方法。如果您有任何问题,请告诉我。

    【讨论】:

    • 你的方法比我的好。我会试着告诉你。
    • 刚刚意识到我在原帖中犯了一个错误。必须在 Warden::Manager 之前插入 Rack::Cors,所以应该使用 insert_before 而不是 use,如下所示:config.middleware.insert_before Warden::Manager, Rack::Cors do
    • 您的方法可以进行一些更改,但效果很好。非常感谢你。请投票支持我的问题,有些白痴投了反对票,我认为这是一个非常有用的问题(和答案)。
    • 对不起@dgellow 我现在无法访问此代码:(
    • @serg 每当我替换“YourAppName”时,javascript 都会抱怨它没有定义。有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 2015-08-10
    • 2014-12-24
    • 2010-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-10
    相关资源
    最近更新 更多