我需要使用一个单一的页面应用程序(反应,Ember,角,我不在乎)与Rails CSRF保护机制。
我想知道是否需要在ApplicationController中创建这样的令牌:
class ApplicationController < ActionController::Base
after_action :set_csrf_cookie
def set_csrf_cookie
cookies["X-CSRF-Token"] = form_authenticity_token
end
end或我可以只创建一个令牌一次。
每个会话还是根据(非获取)请求?
我认为在会话有效之前,令牌仍然有效,对吗?
澄清
每次浏览页面时,我都会看到Rails默认应用程序(服务器呈现的页面)更新csrf令牌。所以每次都变了。
因此,在我的情况下,如果我为每个after_action创建一个新令牌,那么前面的CSRF令牌仍然适合该会话。那么,如何使前一个令牌失效呢?我不得不做?
因为只有我让它失效才有意义,对吧?
发布于 2018-05-08 03:10:52
客户端(SPA)
您只需要每次会话获取一次CSRF令牌。您可以在浏览器中保存它,并将其发送到每个(非获取)请求中。
Rails似乎会在每个请求上生成一个新的CSRF令牌,但它将接受来自该会话的任何生成令牌。在现实中,它只是掩蔽一个单一的令牌使用一次垫每个请求,以防止SSL的破坏攻击。在https://stackoverflow.com/a/49783739/2016618上有更多的细节。您不需要跟踪/存储这些令牌。
服务器端
我强烈建议使用Rails的protect_from_forgery指令,而不是自己在头中编码CSRF令牌。它将为每个请求生成一个不同的掩码令牌。
当然,您自己可以用不多的代码来复制它,但我不明白您为什么需要这样做。
你需要用API来保护CSRF吗?
是的!,如果您正在使用cookie进行身份验证,则需要CSRF保护。这是因为cookie与每个请求一起发送,因此恶意网站可以向您的站点发送POST请求,并代表登录用户执行请求。CSRF令牌可以防止这种情况,因为恶意站点将不知道CSRF令牌。
发布于 2018-06-14 20:45:00
我就回答这个问题。详细信息在本文中解释:https://blog.eq8.eu/article/rails-api-authentication-with-spa-csrf-tokens.html
给定Rails正在为SPA设置cookie。
CSRF令牌在会话的生存期内有效。因此,是的,只要在登录后的会话期间生成一个CSRF令牌就可以了。
class LoginController < ApplicationController
def create
if user_password_match
# ....
cookie[:my_csrf_token]= form_authenticity_token
end
end
end或者,您可以按照建议的方式刷新cookie。
class ApplicationController < ActionController::Base
after_action :set_csrf_cookie
def set_csrf_cookie
cookies["my_csrf_token"] = form_authenticity_token
end
endSPA只需读取cookie并将其设置为标头即可。
两者都同样有效。
或者您只需提供CSRF令牌作为登录响应,SPA就会将其存储在某个地方,并在X-CSRF-Token头中使用它:
curl POST https://api.my-app.com/login.json -d "{"email":'equivalent@eq8.eu", "password":"Hello"}" -H 'ContentType: application/json'
# Cookie with session_id was set
# response:
{ "login": "ok", "csrf": 'yyyyyyyyy" }
# next request
curl POST https://api.my-app.com/transfer_my_money -d "{"to_user_id:":"1234"}" -H "ContentType: application/json" -H "X-CSRF-Token: yyyyyyyyy"给定的Rails只接受标头身份验证。
如果您没有使用cookie发送session_id,那么您的API只使用Authentication头进行身份验证。那你就不需要CSRF保护了。
没有会话cookie,没有CSRF问题!
示例:
curl POST https://api.my-app.com/login.json -d "{"email":'equivalent@eq8.eu", "password":"Hello"}" -H 'ContentType: application/json'
# No cookie/session is set
# response:
{ "login": "ok", "jwt": "xxxxxxxxxxx.xxxxxxxx.xxxxx" }
# Next Request:
curl POST https://api.my-app.com/transfer_my_money -d "{"to_user_id:":"1234"}" -H "ContentType: application/json" -H "Authentication: Bearer xxxxxxxxxxx.xxxxxxxx.xxxxx"再一次,这是只有当你不使用cookies来识别用户!所以在这种情况下CSRF不是一个问题,但您仍然可以防止跨站点脚本攻击,确保您的通信仅限于HTTPs,等等。
发布于 2018-05-07 10:27:40
我不知道你到底面临什么问题。但是,如果在New版本中遇到CSRF问题,并且需要在ajax请求中包含Rails CSRF令牌,则可以按照以下步骤执行。
最近我使用了Rails 5.1应用程序。
当使用ajax调用从API中获取一些数据时,我得到的是CSRF令牌问题:
‘WARNING: Can't verify CSRF token authenticity rails’原因是
默认情况下,Rails 5.1删除了对jquery和jquery_ujs的支持,并添加了
//= require rails-ujs in application.js它做了以下事情:
但默认情况下,它不包括ajax请求的csrf令牌。小心点。我们必须明确地传递它,就像:
$( document ).ready(function() {
$.ajaxSetup({
headers: {
'X-CSRF-Token': Rails.csrfToken()
}
});
----
----
});请注意,在Rails 5.1版本中,您可以在js中获得“Rails”类,并且可以使用这些函数。
更新:--如果您使用的是Rails服务器端和其他前端,您真的不想使用Rails提供的CSRF令牌。因为您所使用的后端服务并不重要。
如果您的目标是阻止CSRF,则需要在后端设置CORS,即Rails后端。Rails现在在初始化器中提供了一个单独的文件。您可以提到哪些站点允许向后端发送ajax请求。
在这里编辑:
config/initializers/cors.rb如果要进行身份验证,请使用basic auth、token auth或JWT。
https://stackoverflow.com/questions/50159847
复制相似问题