Sinatra / Thin:关于CORS xhr预检请求的CSRF警告

时间:2013-08-16 03:18:43

标签: xmlhttprequest sinatra cors thin

我编写了一个服务器来处理跨站点JSON请求。这是一个由ajax调用的API。我得到了它的工作,但我仍然收到一些奇怪的警告。

由于某些API调用是POSTS,因此会有一个预检OPTIONS请求触发此警告(精简输出):

127.0.0.1 - - [15/Aug/2013 22:24:20] "OPTIONS /login HTTP/1.1" 200 - 0.0080
W, [2013-08-15T22:24:20.124254 #3236]  WARN -- : attack prevented by Rack::Prote
ction::HttpOrigin

以下是导致此问题的请求的预检标题:

OPTIONS /login HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:4567
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Access-Control-Request-Headers: origin, content-type
Accept: */*
Referer: http://localhost:4567/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8

此外,我想知道我收到的警告:

SECURITY WARNING: No secret option provided to Rack::Session::Cookie.
This poses a security threat. It is strongly recommended that you
provide a secret to prevent exploits that may be possible from crafted
cookies. This will not be supported in future versions of Rack, and
future versions will even invalidate your existing user cookies.

这是带有应该允许CORS xhr的标题的服务器代码:

enable :sessions

before do

  headers['Access-Control-Allow-Origin'] = 'http://localhost:4567'
  headers['Access-Control-Allow-Headers'] = 'origin, content-type, accept'
  headers['Access-Control-Allow-Credentials'] = 'true'

  if request.request_method == 'OPTIONS'
    headers["Access-Control-Allow-Methods"] = "POST, GET"
    halt 200
  end
end

1 个答案:

答案 0 :(得分:1)

这实际上是两个相关的问题,我将一次解决一个问题。

  1. 根据this SO question,您似乎需要向Sinatra提供原始白名单。它本来要做的就是保护你免受可能伤害用户的Cross Site Scripting Attacks。但是,在某些情况下,您确实希望允许跨站点脚本执行。为此,您可以执行以下操作:

    set :protection, :origin_whitelist => ['http://web.example.com']
    

    标题仅适用于用户的浏览器,但Rack也需要权限。两道防线。 有关更多信息,请参阅documentation for Rack::Protection(这是Sinatra在此处使用的内容)。

  2. “秘密选项”错误是指Rack :: Session上的设置。当您使用Rack :: Session功能时,您可以将其传递给秘密,如下所示:

    use Rack::Session::Cookie, :key => 'rack.session',
                               :domain => 'foo.com',
                               :path => '/',
                               :expire_after => 2592000,
                               :secret => 'change_me'
    

    执行上述操作而不是简单的enable :sessions。 您还可以找到documentation for Rack::Session here