使用 Devise 3 和 Backbone 进行用户身份验证的最佳方法是什么? [英] What is the best way to user authentication with Devise 3 and Backbone?
问题描述
我正在使用这个堆栈:
- 使用 Rails 4 和 Devise 3.2 的核心 API RESTful
- 另一个使用 Backbone 的应用程序/立场
我已经阅读了很多文章、手册、stackoverflow 主题、谷歌随机结果、博客等,但都非常不推荐.
I have read many articles, manuals, stackoverflow topics, google random results, blogs, etc, but are all very deprecated.
使用实用的方法(tl;dr here)我只需要在不同服务器立场下的 Devise 3 和 Backbone 之间进行真正的会话并保持它,就像两个独立的项目一样.远程登录,你懂的.
Using a practical approach (tl;dr here) I just need get a real session between Devise 3 and Backbone in different server stances and holding it, like two separate projects. Remote login, you know.
我真的坚持这一点,所以我非常感谢您的建议.
I'm really stuck with that so I would greatly appreciate your suggestions.
谢谢你们.
推荐答案
就我个人而言,我在我的项目中遇到了同样的情况,使用 Angular 而不是 Backbone 作为前端,并且使用带有 Devise 的 Rails 4 API.我会尽量为你总结一下,假设我回答对了你的问题.
Personally I have the same situation in my project with Angular instead of Backbone as a front-end and Rails 4 API with Devise. I will try to sum things up for you in the assumption that I got your question right.
要在您的场景中正确使用会话,您需要确保:
To work correctly with the sessions in your scenario you need to be sure that:
- 浏览器正确处理通信(即它们不会因为请求不符合 CORS 政策而弄乱您的数据)
- 并且,您的请求通过 Rails CSRF 保护
请阅读这篇关于 CORS 的文章.如果您不熟悉 CORS,这篇文章应该为我的回答提供必要的背景.关于 CSRF 保护的一些信息是这里
Please, read this article about CORS. If you are not familiar with CORS the article should provide necessary background for my answer. Some info about CSRF protection is here
以下是您的场景分步说明:
Here is your scenario step-by-step:
- Backbone.js 发送
GET
请求,例如http://yourserver/signin
- Rails 服务器发送会话 cookie,这些 cookie 将存储在浏览器和 CSRF 令牌中,这些令牌可以存储在您的 Backbone 应用程序中的某个位置.
- Backbone.js 发送带有用户凭据(名称、密码)和 CSRF 令牌的
POST
请求,并在 cookie 中发送当前未经授权的会话.请求包含会话信息是至关重要的.否则,它会在 Rails 端获得不同的 CSRF 令牌,您将收到警告:无法验证 CSRF 令牌真实性
消息. - 如果凭据正确,Backbone.js 会取回授权会话.
- Backbone.js sends
GET
request such ashttp://yourserver/signin
- Rails Server sends session cookie that will be stored in the browser and CSRF token, which can be stored somewhere within your Backbone application.
- Backbone.js sends
POST
request with user credentials (name, password) and CSRF token in headers and current unauthorized session in cookies. It is crucial that request contains session information. Otherwise it will be granted different CSRF token on Rails side and you will getWARNING: Can't verify CSRF token authenticity
message. - Backbone.js gets authorized session back if the credentials are correct.
以下是让它工作的方法:
Here is what can be done to get it working:
Rails 后端应该正确响应来自前端的请求.这意味着它应该:
Rails backend should respond correctly to requests from front-end. Which means it should:
- 响应
OPTIONS
请求(预检请求) - 发送正确的 CORS 标头
- 能够与前端通信 CSRF 令牌
前端应该:
- 能够发送带有凭据的请求
- 获取并使用正确的CSRF令牌
教你的 Rails 后端响应 CORS 请求的最简单方法是使用rack-cors gem.这也将提供正确的 CORS 标头.
The simplest way to teach your Rails back-end to respond to CORS requests is to use rack-cors gem. This will also provide correct CORS headers.
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 令牌.自定义设计控制器应该完美地处理这个任务.
Last thing on a backend side is to provide CSRF token. Custom Devise controller should handle this task perfectly.
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
)时,您需要 CSRF 令牌,当您通过 POST
请求(>create
) 以及当您通过发送 DELETE
请求 (destroy
) 退出应用程序时.如果您在退出时不发送 CSRF 令牌,则在不重新加载页面的情况下将无法登录.
Note that you need CSRF token when you send first GET
request (new
), when you submit credentials through POST
request (create
) and when you sign out of your application by sending DELETE
request (destroy
). If you don't send CSRF token on sign out you won't be able to sign in without reloading the page.
在 config/routes.rb 中的某处不要忘记指定您现在正在使用自定义控制器:
And somewhere in config/routes.rb don't forget to specify that you are now using custom controller:
/config/routes.rb
devise_for :users, :controllers => {:sessions => "sessions"}
现在,到前端.请查看这个脚本,它覆盖了标准Backbone.sync
并处理与 Rails 服务器的通信.这几乎是好的,需要进行一些更正:
Now, to the front-end. Please, have a look at this script that overrides standard Backbone.sync
and handles communication with Rails server.
It is almost good with couple of corrections needed:
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);
};
}
我不确定这是否可以作为您问题的完整答案,但至少它是一个起点.这可能不是最好的方法,但它是方法.如果您有任何问题,请告诉我.
I'm not sure this qualifies as a complete answer to your question, but at least it is something to start from. It might not be the best way, but it is the way. Let me know if you have any questions.
这篇关于使用 Devise 3 和 Backbone 进行用户身份验证的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!