CORS 问题:实际出现错误“不存在‘Access-Control-Allow-Origin’标头”
Posted
技术标签:
【中文标题】CORS 问题:实际出现错误“不存在‘Access-Control-Allow-Origin’标头”【英文标题】:CORS issue: Getting error "No 'Access-Control-Allow-Origin' header is present" when it actually is 【发布时间】:2014-01-10 13:06:45 【问题描述】:我怀疑为我的应用程序提供服务的后端是否重要,但如果你关心的话,我将 rack-cors 与 Rails 4.0 应用程序一起使用。
使用 jQuery,我向我的应用发送 PATCH
请求,如下所示:
$.ajax(
url: "http://example.com/whatever",
type: "PATCH",
data: something: "something else"
)
当我从 Chrome 触发此调用时,我看到一个成功的 OPTIONS
请求发出,它从我的服务器返回这些标头:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:accept, content-type
Access-Control-Allow-Methods:GET, PUT, PATCH, OPTIONS
Access-Control-Allow-Origin: http://sending-app.localhost:3000
Access-Control-Expose-Headers:
Access-Control-Max-Age:15
然后我看到一个PATCH
请求出去了,它抛出了这个错误:
XMLHttpRequest 无法加载 http://example.com/whatever。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问 Origin 'http://sending-app.localhost:3000'。
我尝试从PATCH
切换到PUT
,结果相同。
这对我来说没有任何意义。怎么回事?
更新:我的 config/application.rb
我以为标题说明了整个故事,但由于人们感到困惑,这是我的 config/application.rb
文件,这是 Rails 的 rack-cors 插件的配置方式:
config.middleware.use Rack::Cors do
allow do
origins '*'
resource '*',
:headers => :any,
:methods => [:get, :put, :patch, :options],
:max_age => 15
end
end
【问题讨论】:
你的application.rb
是什么样的?
@RichPeck 我已经添加了我的application.rb
,这是值得的。
【参考方案1】:
在动作中排除 Rails CSRF 检查;)
也就是说,Rails 通过更新/创建请求检查真实性令牌。在您的 Rails 应用程序中,此令牌会添加到您的所有表单中。但是对于 javascript 请求,包括它是棘手的。
您可以通过将其添加到您的控制器来跳过检查它的操作:
skip_before_filter :verify_authenticity_token, :only => [:update]
顺便说一句,您的问题与 CORS 无关,您在浏览器中收到了错误消息。 Rails 日志讲述了真实的故事。
【讨论】:
-1 当您可以简单地将 csrf 令牌附加到所有 ajax 发送时,为什么要跳过 csrf(在下面发布答案) 为什么是-1?这是解决问题的方法。该请求来自一个不知道 CSRF 令牌的单独应用程序。 因为解决办法是禁用csrf。这听起来像是一个安全漏洞。但是,如果它是一个经过身份验证的请求,那听起来不错。 很公平。您不能期望外部服务的用户提供 CSRF 令牌。这是从一个应用程序触发的,而端点位于另一个应用程序中,因此它跨域。如果这一切都在同一个应用程序中,我会同意你的看法。 快进到 2018 年,现在skip_before_action
使用 Rails 5(技术上也使用 Rails 4)。【参考方案2】:
您可能希望将此添加到您的 config/application.rb
文件中:
#config/application.rb
config.middleware.use Rack::Cors do
allow do
origins '*'
resource '/*', :headers => :any, :methods => :patch
end
end
resource
部分是您定义端点可以接受的方法/请求的地方!
希望对你有帮助
【讨论】:
对不起,我认为只显示返回的标题就表明我已经这样做了。这是 HTTP 标头的问题,而不是 Rails 配置的问题,所以我想让这个问题通常可以访问,而不是用不必要的 Rails 东西弄乱它。我现在添加了我在 config/application.rb 中的rack-cors
设置。
感谢 bud - 您在什么环境下看到此错误?生产和/或开发?你能描述一下设置吗?
我在生产中看到了这个,它在 Heroku 上。它非常接近香草 Rails 4; rack-cors
是我添加的唯一 Rack 中间件。
奇怪 - 我们已经使用 Heroku 生产了一段时间,并且让这个功能正常工作。您是否设置了路由和控制器操作来处理请求?
我当然愿意!我有这个 PATCH
端点的规格,它可以做我想做的一切。【参考方案3】:
这是一些奇怪的东西。
A) 作为试用版,您应该尝试输入 *
作为您允许的来源。
B) 这是空格问题吗?冒号后面的某些选项中没有空格。
C) 这看起来像一个“预检请求”(https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS)。预检请求是不使用您应该使用的“application/x-www-form-urlencoded”的请求。 http://api.jquery.com/jquery.ajax/ 声明默认内容类型是 x-www-form-urlencoded,并且您没有覆盖内容类型。这意味着不需要有 2 个请求。
D) 如上所述,CSRF 可能是问题所在。我不是铁路人。如果这是您可能想要做的问题是将您的 CSRF 令牌附加到所有 ajax 发送,如下所示:
$.ajaxSetup(
beforeSend:function(xhr, settings)
xhr.setRequestHeader('X-CSRF-Token', '<%= csrf_token_value %>');
);
还有其他几种方法可以做到这一点。这取决于您的框架/库需要什么。
【讨论】:
如果请求不是来自完全不同的应用程序,那就没问题了。我们在同一个团队中工作,CSRF 是这种情况下的问题。【参考方案4】:这是我从旧的 SO 帖子中发现的解决 csrf 问题的方法:
# In application_controller.rb
protect_from_forgery
after_filter :set_csrf_cookie
def set_csrf_cookie
cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
end
protected
# In Rails 4.2 and above
def verified_request?
super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
end
【讨论】:
以上是关于CORS 问题:实际出现错误“不存在‘Access-Control-Allow-Origin’标头”的主要内容,如果未能解决你的问题,请参考以下文章
调用我的 API 时在我的反应应用程序上出现此 CORS 错误 - 请求的资源上不存在“Access-Control-Allow-Origin”标头
CORS 错误:不存在“Access-Control-Allow-Origin”标头
Javascript CORS - 不存在“Access-Control-Allow-Origin”标头