问题描述
早在2011年2月时,Rails改为的,即使是那些对于API端点。我理解为什么这是浏览器请求一个重要的变化的解释,但博客文章不提供一个API应如何处理变化的任何建议。
Back in February 2011, Rails was changed to require the CSRF token for all non-GET requests, even those for an API endpoint. I understand the explanation for why this is an important change for browser requests, but that blog post does not offer any advice for how an API should handle the change.
我不感兴趣,禁用CSRF保护某些动作。
I am not interested in disabling CSRF protection for certain actions.
如何的API应该应对这种变化?那是一个API客户端发出GET请求API来获取一个CSRF令牌的预期,那么包括该届会议期间每个请求该令牌?
How are APIs supposed to deal with this change? Is the expectation that an API client makes a GET request to the API to get a CSRF token, then includes that token in every request during that session?
看来,令牌不从一个POST切换到另一个。是安全的假设,令牌将不会在会话期间改变?
It appears that the token does not change from one POST to another. Is it safe to assume that the token will not change for the duration of the session?
当会话过期我可不乐意额外的错误处理,但我想这是不是让每一个POST / PUT之前得到令牌/ DELETE请求越好。
I don't relish the extra error handling when the session expires, but I suppose it is better than having to GET a token before every POST/PUT/DELETE request.
推荐答案
老问题,但安全性是足够重要的,我觉得它值得一个完整的答案。正如本有仍然有一些跨站请求伪造的风险甚至与API的。是的浏览器应该在默认情况下,以防止这一点,但你没有用户已经安装了浏览器和插件的完全控制,它仍应被视为一种最佳做法,以防止CSRF您的API中。
Old question but security is important enough that I feel it deserves a complete answer. As discussed in this question there are still some risk of CSRF even with APIs. Yes browsers are supposed to guard against this by default, but as you don't have complete control of the browser and plugins the user has installed, it's should still be considered a best practice to protect against CSRF in your API.
我已经看到了它有时做的方法是分析从HTML页面本身CSRF元标记。我真的不喜欢这个,虽然,因为它不与方式合身了很多单页+ API的应用程序今天的工作,我觉得CSRF令牌应该每个请求被发送不管它是否是HTML,JSON或XML。
The way I've seen it done sometimes is to parse the CSRF meta tag from the HTML page itself. I don't really like this though as it doesn't fit well with the way a lot of single page + API apps work today and I feel the CSRF token should be sent in every request regardless of whether it's HTML, JSON or XML.
所以,我建议,而不是通过传递一个CSRF令牌作为一个cookie或头值过滤所有请求后。该API可以简单地重新提交回为的头值X-CSRF令牌
这已经Rails的检查。
So I'd suggest instead passing a CSRF token as a cookie or header value via an after filter for all requests. The API can simply re-submit that back as a header value of X-CSRF-Token
which Rails already checks.
这是我如何与AngularJS做的:
This is how I did it with AngularJS:
# In my ApplicationController
after_filter :set_csrf_cookie
def set_csrf_cookie
if protect_against_forgery?
cookies['XSRF-TOKEN'] = form_authenticity_token
end
end
XSRF-TOKEN
但随时将其命名为任何你想要你的目的。然后,当你提交POST / PUT / DELETE你应该设置头属性 X-CSRF令牌
这Rails会自动查找。
AngularJS automatically looks for a cookie named XSRF-TOKEN
but feel free to name it anything you want for your purposes. Then when you submit a POST/PUT/DELETE you should to set the header property X-CSRF-Token
which Rails automatically looks for.
不幸的是,AngualrJS已经发回了 XSRF-TOKEN
饼干在 X-XSRF-TOKEN
的头值。这很容易覆盖Rails的默认行为的ApplicationController
这样的,以适应这样的:
Unfortunately, AngualrJS already sends back the XSRF-TOKEN
cookie in a header value of X-XSRF-TOKEN
. It's easy to override Rails' default behaviour to accomodate this in ApplicationController
like this:
protected
def verified_request?
super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
end
有关的Rails 4.2有一个内置在辅助现在用于验证CSRF应使用
For Rails 4.2 there is a built in helper now for validating CSRF that should be used.
protected
def verified_request?
super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
end
我希望这是有帮助的。
I hope that's helpful.
编辑:在为我提交了Rails的拉请求对这个讨论它出来的传递CSRF令牌通过登录的API是一个特别不好的做法(比如,有人可能会为您的网站使用的用户凭据,而不是令牌创建第三方登录)。所以cavet自负。它是由你来决定你是有关你的应用程序如何关注。在这种情况下,你仍然可以使用上面的方法,但只发回CSRF的cookie到已为每个请求认证的会话,而不是浏览器。这将prevent提交有效的登录,而无需使用CSRF元标记。
In a discussion on this for a Rails pull-request I submitted it came out that passing the CSRF token through the API for login is a particularly bad practice (e.g., someone could create third-party login for your site that uses user credentials instead of tokens). So cavet emptor. It's up to you to decide how concerned you are about that for your application. In this case you could still use the above approach but only send back the CSRF cookie to a browser that already has an authenticated session and not for every request. This will prevent submitting a valid login without using the CSRF meta tag.
这篇关于Rails的API设计,无禁用CSRF保护的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!