IE11中的CORS请求

26

我的登录页面向不同URL的应用程序网站发出CORS(跨域资源共享)请求。我有一个简单的页面,我会ping一下以确定用户是否已经登录,如果是,则重定向他们,否则显示登录页面。我使用jQuery。

在Safari、Chrome、Firefox中都能正常工作……但在IE中不行(当然)。根据微软的说法,IE 10及更高版本应该支持带有withCredentials的CORS请求

我正在使用jquery-2.0.3.min.js。

为什么IE11不能正常工作?有什么想法吗?

编辑:看起来它部分地工作了,因为它现在返回一个值{"id":false}。这种情况每次都发生,这意味着服务器从未获得凭据。我还发布了我的is_logged_in页面,我正在使用CodeIgniter框架。

编辑:在启用了IE安全设置下的“允许跨域数据源”后,我不再收到任何错误消息。

我收到的确切错误是:

SEC7118: XMLHttpRequest for http://mysite.net/guest/is_logged_in required Cross Origin Resource Sharing (CORS).

$.ajax({
url: 'http://mysite.net/guest/is_logged_in',
type: 'POST',
crossDomain: true,
xhrFields: {
       withCredentials: true
  },

dataType: 'json',
success: function(data) {

    if(data.id) {
        window.location.replace("http://mysite.net");
    }
}
});

public function is_logged_in()
{
    $allowed = array(
        'http://mysite.net',
        'http://www.mysite.net',
        'http://www.mysite.com',
    );

    $url = $_SERVER['HTTP_REFERER'];
    $url = substr($url, 0, strpos($url, '/', 8));
    if(isset($_SERVER['HTTP_ORIGIN']))
    {
        if(in_array($_SERVER['HTTP_ORIGIN'], $allowed))
        {
            $this->output->set_header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
        }
    }
    else
    {
        if(in_array($url, $allowed))
        {
            $this->output->set_header('Access-Control-Allow-Origin: ' . $url);
        }
    }


    $this->output->set_header('Access-Control-Allow-Headers: X-Requested-With');
    $this->output->set_header('Access-Control-Allow-Credentials: true');
    $this->output->set_header("Access-Control-Expose-Headers: Access-Control-Allow-Origin");


    //TODO: Try to detect if this is an ajax request, and disallow it if not.

    $data = new stdClass();
    $this->load->library("ion_auth");
    if($this->ion_auth->logged_in())
    {
        $data->name = $this->ion_auth->user()->row()->first_name;
        $data->id = $this->ion_auth->get_user_id();
    } else {
        $data->id = false;
    }

    $this->output->set_output(json_encode($data));

}

提前致谢


1
你是否在Internet -> 安全选项中将“杂项->跨域访问数据源”设置为禁用了? - eithed
你在成功时进行重定向的事实让我想知道你是否真的需要使用ajax。 - Kevin B
你可能在IE缓存中有这个js的旧版本(在添加“withCredentials”设置之前)。我只是猜测。IE也喜欢缓存数据,包括ajax请求。确保你使用类似于:$.ajaxSetup({cache: false})的东西。 - James Adam
它不再给出错误提示的事实表明ajax已成功(或者至少服务器响应并且脚本具有继续进行的凭据)。服务器输出的响应是什么?编辑:也许是location.replace的问题?首先尝试仅使用window.alert(data)检查代码是否进入成功块。 - eithed
我进行了更深入的挖掘:我打开了网络详细信息并获取了ajax调用的响应。它包含一个PHP错误,因为IE不发送HTTP_ORIGIN头,而Chrome、Safari和FF则会发送。我修复了这个问题,现在我收到了正确的“未登录”响应。这意味着它正在进行检查,检查失败,并返回false。 - Drew
显示剩余3条评论
6个回答

20
将“跨域访问数据源”设置为启用会关闭IE中的跨域检查,非常不安全。相反,您需要确保目标第三方资源发送有效的P3P策略,表明它不会对用户的隐私造成不良影响。

2
我曾经研究过P3P,但最终决定不使用它,因为它并没有得到广泛应用。这段话来自维基百科。
P3P是由万维网联盟(W3C)开发的,并于2002年4月16日正式推荐。然而,开发工作很快就停止了,P3P的实现非常少。微软Internet Explorer是唯一支持P3P的主要浏览器。
- Drew
45
你:「为什么我的代码在IE上不能运行?」我:「因为IE需要P3P。」你:「但是除了IE之外,P3P并没有真正被使用啊。」我:「...」 - EricLaw
6
那是表述我的立场的非常优雅的方式(:如果这是一个更重要的功能,是的,我会实施P3P政策。 我会给你答案,因为你在技术上是正确的,而那是最好的正确。 - Drew
2
我在响应头中添加了P3P,但仍然无法正常工作。我只能更改“跨域访问数据源”以允许其正常工作! - kiford
3
在StackOverflow上提问的正确方式是点击页面右上角的大蓝色"Ask a question"按钮。你要问的问题是:"如何使用CORS允许跨域访问数据?",这个问题可能已经被问过很多次了。 - EricLaw
显示剩余6条评论

15

找到了问题所在。

我遇到了类似的问题(不仅限于GWT,一般有关CORS的问题)。 原来浏览器设置阻止了第三方cookie (IE10 > Internet选项 > 隐私 > 高级 > 第三方cookie > 接受)。为了解决这个问题,我勾选了“覆盖自动处理cookie”,“接受”(第三方cookie)以及“始终允许会话cookie”。

Andrew在这里回答了这个问题:CORS在IE10中无法使用cookie

编辑:(现在我知道该搜索什么了)如果其他人也遇到了这个问题,这个问题也可能有所帮助。Internet Explorer 10忽略XMLHttpRequest 'xhr.withCredentials = true'


1
是的,这对我也解决了一个类似的问题。 - ianbeks

6

我们遇到了一个问题,除了其他浏览器之外,IE11在请求中发送了Access-Control-Request-Headers: accept,因此必须将“accept”添加到允许的跨域配置allowedHeaders中,因为它似乎不是默认的Spring cors配置的一部分。


在我的情况下,它发送了 Access-Control-Request-Headers: content-type, accept - halfpastfour.am
这个建议帮助我解决了使用AWS API Gateway v2 (httpapi)时IE11的CORS问题。在CORS配置中,我们的Access-Control-Allow-Headers白名单现在是:x-apigateway-header、authorization、content-type和accept。它也可以与Axios Vue库一起使用(看到另一个答案提到他们无法让它工作)。谢谢! - twamley

1

IE10要求服务器在跨域请求中除了CORS头之外,还返回有效的P3P策略。以下是返回服务器端P3P头的PHP示例代码。

  $szOrigin = $_SERVER['HTTP_ORIGIN'];
  if ($szOrigin != null)
  {
        header("Access-Control-Allow-Origin: $szOrigin");
        header("Access-Control-Allow-Credentials: true");
        header("P3P: CP=\"ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\"");
  }

0

我曾经遇到过类似的问题,并发现无论是axios还是jquery都不能与Internet Explorer和预检/CORS问题一起使用。只有老式的XMLhttpRequest可以工作。因为在纯XMLhttpRequest中,我们可以这样做:

if (xhttp.readyState == 4 && xhttp.status == 200)

看起来 axios 和 jquery 考虑的是状态而不是 readyState - 它们会以某种方式解释存在 CORS 问题 - 并且在 IE 中需要几个时钟周期才能达到 readyState == 4。


0
经过一番探索,我发现我使用ajax进行ping的页面在互联网区域,而我的当前页面在内部网络区域。
IE 11对于互联网站点启用了“受保护模式”,当启用时,即使cookie属于该域,也不会将其发送到我正在ping的站点。
将该页面添加到信任站点中或禁用“受保护模式”可以解决问题。
请注意,当两个站点都位于互联网区域时,即使启用了“受保护模式”,也不会出现此问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接