根据Rspec的说法,为什么机架式磁盘不能过滤传入的请求

ste*_*ble 1 rspec ruby-on-rails cors rails-api rack-cors

我想我的Rails 5 API专用应用程序,现在正在运行http://localhost:3000,只接受来自我的NodeJS前端应用程序的请求,现在正在运行http://localhost:8888.

所以我配置/config/initializers/cors.rb如下:

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins "http://localhost:8888"
    resource "*",
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end
Run Code Online (Sandbox Code Playgroud)

我写了这个测试:

#/spec/request/cors_request_spec.rb

RSpec.feature "CORS protection", type: :request do
  it "should accept a request from a whitelisted domain" do
    get "/api/v1/bodies.json", nil, "HTTP_ORIGIN": "http://localhost:8888"
    expect(response.status).to eql(200)
  end
  it "should reject a request from a non-whitelisted domain" do
    get "/api/v1/bodies.json", nil, "HTTP_ORIGIN": "https://foreign.domain"
    expect(response.status).to eql(406)
  end
end
Run Code Online (Sandbox Code Playgroud)

第一个测试按预期传递.但第二个是失败,响应代码为200.为什么?

(顺便说一句,我没有使用406响应代码;只是表示请求不会被执行的代码.)

sid*_*ker 8

CORS配置不会阻止服务器根据Origin请求标头的值接受请求.你不能只通过CORS配置来做到这一点.

在服务器上配置CORS支持时,服务器执行的所有操作都只是发送Access-Control-Allow-Origin响应头和其他CORS响应头.

CORS限制的实际执行仅由浏览器完成.它不是由服务器强制执行的.

协议的工作方式是,无论您在服务器端进行哪种CORS配置,服务器都会继续接受来自所有客户端的请求,否则会接收来自所有客户端的请求,因此来自所有来源的所有客户端都会继续从服务器获得响应,就像否则就会.

因此,即使您在浏览器中发现错误,您的前端JavaScript代码中的跨源请求失败,您仍然可以在浏览器devtools中看到响应.

但仅仅因为您的浏览器可以看到响应并不意味着浏览器会将其暴露给您的前端JavaScript代码.浏览器仅将来自跨源请求的响应暴露给在特定源运行的前端代码(如果请求被发送到opts-in的服务器,以通过响应Access-Control-Allow-Origin允许该源的标头来允许请求).

因此,对于具有Origin请求标头匹配的任何请求https://foreign.domain,问题中的配置代码段应该导致浏览器在客户端发出一条消息,说http://localhost:3000/api/v1/bodies.json无法加载,因为Access-Control-Allow-Origin响应中没有响应标头(因为您的配置导致服务器只有发送该标题以回复您列入白名单的来源).

但是你可以通过CORS做到这一切.您无法通过在服务器端执行任何CORS配置来阻止服务器端接受和响应来自特定源的请求.如果你想这样做,你需要使用除CORS配置之外的其他东西.