request.xhr CORS布局失败

时间:2014-05-12 13:11:29

标签: ruby-on-rails routes subdomain cors

如果我向我们的子域控制器发送remote: true请求,我们的布局呈现(它不应该)

在操作中测试了request.xhr?方法后,它返回了您期望的nil(不是真/假)。这适用于非CORS ajax。它只停止使用CORS-ajax(用于子域)


以下是代码:

#app/views/controller/view.html.haml
= link_to "test", new_user_session_url, remote: :true

#routes
new_user_session_path   GET  /login(.:format)    admin/users/sessions#new {:subdomain=>"test"}

响应发生&我们得到一个布局

我们不需要布局,没有CORS

#app/controllers/application_controller.rb
layout :layout_select

  def layout_select
    if request.xhr?
      false
    else
      devise_controller? ? "admin" : "application"
    end
  end

我们制定了CORS政策&工作。但是,似乎我们的CORS请求未被视为xhr有什么想法吗?

2 个答案:

答案 0 :(得分:3)

根据Mike Campbell的评论,我能够确定CORS requests are not treated as ajax (xhr) by default

问题在于在Ajax请求上传递的头文件。标准的ajax传递以下标题:

  #actionpack/lib/action_dispatch/http/request.rb
  def xhr?
       @env['HTTP_X_REQUESTED_WITH'] =~ /XMLHttpRequest/ 
  end

这是通过"裸体" Ajax请求,允许xhr?方法返回true或false。问题是在CORS ajax调用中,此标头未通过。我不知道为什么,但它只是发送一个ORIGIN标题

Github提出的修正建议包括:

 uri.host != @env['HTTP_HOST'] || uri.scheme != @env['rack.url_scheme'] || uri.port != @env['HTTP_PORT'].to_i

这基本上会根据请求是否来自与脚本相同的域返回布尔响应。虽然这是不安全的,但它引导我两个修复:

  
      
  1. 将新的cors?方法附加到Rails核心
  2.   
  3. 通过CORS请求发送http_x_requested_with标头
  4.   

考虑到我们只是尝试使用请求访问子域,我们觉得编辑Rails核心有点矫枉过正,尽管是正确的。相反,我们发现在jquery中使用内置的headers参数会有所帮助:

$.ajaxSetup({ headers: {"X-Requested-With": "XMLHttpRequest"}});

虽然这有效,但我很想知道它可能出现的任何安全问题。此外,我们是否可以使用json和其他格式访问

答案 1 :(得分:0)

这是因为同源政策。请仔细阅读这篇文章:HTTP access control (CORS)

可能的解决方案是:

  • 制作简单请求 - 而不是remote: true执行通常的表单帖子,或者$.getJSON()可能会工作(不确定)。
  • 实施预检请求 - 您需要在服务器上实施OPTIONS请求的响应。
  • 如果您需要维护cookie,那么您还需要编写自定义的ajax代码,例如。 $.ajax({url: a_cross_domain_url, crossDomain: true, xhrFields: {withCredentials: true}});并从服务器返回一些特定标头。