在您的 Sinatra 应用程序中使用它应该可以解决您的问题:
set :protection, :except => [:json_csrf]
更好的解决方案可能是将 Sinatra 升级到 1.4,它使用 Rack::Protection 1.5,不会导致您看到的问题。
问题是当您使用 Content-Type: application/json 响应时,您的 in 版本与CORSRackProtection::JsonCsrf
不兼容。这是机架保护中旧 json_csrf.rb的片段:
def call(env)
status, headers, body = app.call(env)
if headers['Content-Type'].to_s.split(';', 2).first =~ /^\s*application\/json\s*$/
if referrer(env) != Request.new(env).host
result = react(env)
warn env, "attack prevented by #{self.class}"
end
end
result or [status, headers, body]
end
application/json
您可以看到,当引用者与服务器不是来自同一主机时,这会拒绝具有响应的请求。
这个问题在更高版本的 rack-protection 中得到了解决,它现在考虑请求是否是 XMLHttpRequest:
def has_vector?(request, headers)
return false if request.xhr?
return false unless headers['Content-Type'].to_s.split(';', 2).first =~ /^\s*application\/json\s*$/
origin(request.env).nil? and referrer(request.env) != request.host
end
如果您使用的是 Sinatra 1.3.2 并且无法升级,解决方案是禁用此特定保护。使用 CORS,您可以显式启用跨域 XHR 请求。Sinatra 允许您完全禁用保护,或禁用特定组件Rack::Protection
(请参阅Sinatra 文档中的“配置攻击保护”)。
Rack::Protection
提供12 个中间件组件,帮助抵御常见攻击:
Rack::Protection::AuthenticityToken
Rack::Protection::EscapedParams
Rack::Protection::FormToken
Rack::Protection::FrameOptions
Rack::Protection::HttpOrigin
Rack::Protection::IPSpoofing
Rack::Protection::JsonCsrf
Rack::Protection::PathTraversal
Rack::Protection::RemoteReferrer
Rack::Protection::RemoteToken
Rack::Protection::SessionHijacking
Rack::Protection::XssHeader
在撰写本文时,当您使用 Rack::Protection 中间件时,除了四个之外,所有这些都会自动加载(Rack::Protection::AuthenticityToken
、Rack::Protection::FormToken
、Rack::Protection::RemoteReferrer
,并且Rack::Protection::EscapedParams
必须显式添加)。
Sinatra 使用 Rack::Protection 的默认设置,但有一个例外:它只添加SessionHijacking
并且RemoteToken
启用会话。
最后,如果您尝试将 CORS 与 Sinatra 一起使用,您可以尝试rack-cors,它会为您处理很多细节。