IE11 CORS 拒绝 https 上的 OPTIONS

Posted

技术标签:

【中文标题】IE11 CORS 拒绝 https 上的 OPTIONS【英文标题】:IE11 CORS rejecting OPTIONS on https 【发布时间】:2016-04-25 05:39:57 【问题描述】:

IE11 出于某种原因拒绝 PUT 请求,但仅在我使用 https 时。 我很难找到问题,因为使用 http、localhost 和其他浏览器都可以正常工作。

控制台显示两个错误

SEC7124: Request method PUT was not present in the Access-Control-Allow-Methods list.
SCRIPT7002: XMLHttpRequest: Network Error 0x80070005, Access is denied.

浏览器发出的OPTION请求是

Accept: */*
Accept-Encoding: gzip, deflate
Access-Control-Request-Headers: accept, content-type, session-id
Access-Control-Request-Method: PUT   
Cache-Control: no-cache 
Connection: Keep-Alive  
Content-Length: 0  
Host: api.domain.com  
Origin: https://portal.domain.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko

服务器的响应如下:

X-Powered-By: Servlet/2.5
Server: server
Content-Encoding: gzip
Access-Control-Expose-Headers: Session-Id
Access-Control-Allow-Origin: *
Access-Control-Max-Age: -1
Allow: OPTIONS,GET,HEAD,PUT
Access-Control-Allow-Methods: OPTIONS, GET, POST, PUT, DELETE
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: accept, origin, Content-Type, session-id, authorization, portal-url
Content-Type: application/vnd.sun.wadl+xml
Content-Length: 352
Date: Tue, 19 Jan 2016 15:33:38 GMT

AngularJS 用于客户端标准 $http PUT 被使用。 服务器端使用带有 jersey 的 Java,处理 CORS 的请求过滤器如下:

 public ContainerResponse filter( final ContainerRequest request, final ContainerResponse response )

    if ( request.getHeaderValue( "Origin" ) != null ) 
    
        final MultivaluedMap<String, Object> headers = response.getHttpHeaders();
        headers.add( "Access-Control-Allow-Origin", "*" );
        headers.add( "Access-Control-Expose-Headers", "Session-Id" );
        headers.add( "Access-Control-Allow-Credentials", Boolean.TRUE.toString() );
    

    if ( "OPTIONS".equals( request.getMethod() ) ) 
    
        final MultivaluedMap<String, Object> headers = response.getHttpHeaders();
        for ( String method : ["OPTIONS", "GET", "POST", "PUT", "DELETE"] ) 
        
            headers.add( "Access-Control-Allow-Methods", method );
        
        headers.add( "Access-Control-Allow-Headers",
                "accept, origin, Content-Type, session-id, authorization, portal-url, " 
                + "If-Modified-Since, Cache-Control, Pragma" );
        headers.add( "Access-Control-Max-Age", "-1" );            
    

    return response;

也许你可以看到这可能有什么问题。

谢谢

【问题讨论】:

尝试设置实际原点而不是* 检查 IE 控制台(F12 打开 devtools)是否有错误。应该有一条消息描述浏览器拒绝请求的原因。出乎意料 - allow credentials=true 应附有非星号允许来源。 @OlegEstekhin 错误消息就在 OP 问题的顶部 @OlegEstekhin 是的,错误是 SEC7124:访问控制允许方法列表中不存在请求方法 PUT。 SCRIPT7002:XMLHttpRequest:网络错误 0x80070005,访问被拒绝。但是如何避免 * 在像 api 这样的响应中也将在移动设备上使用,并且它们没有静态来源 尝试设置完整的原点而不是 * 作为允许原点标头。另外,只在允许方法头中设置 PUT。让我知道它是否有效。 【参考方案1】:

我已经设法找到了问题。

我在 https 上看到这个问题只是因为门户和主机位于不同的域中。我无法在 localhost 上复制该问题,因为服务器和门户都在同一个域上。这意味着没有发送 OPTION 请求,并且一切都按预期工作。在 localhost 上运行门户并使用 IP 地址而不是 localhost 作为服务器 URL 后,OPTION 请求包含在请求中,我可以复制我的问题。

而它本身的问题在于服务器上的以下代码

    for ( String method : ["OPTIONS", "GET", "POST", "PUT", "DELETE"] ) 
    
        headers.add( "Access-Control-Allow-Methods", method );
    

由于某种原因,IE 不喜欢多个 Access-Control-Allow-Methods 标头。将代码更改为以下问题后得到解决。

 List<String> ALLOWED_METHODS = Arrays.asList( "OPTIONS", "GET", "POST", "PUT", "DELETE" );
 headers.add( "Access-Control-Allow-Methods", ALLOWED_METHODS );

【讨论】:

以上是关于IE11 CORS 拒绝 https 上的 OPTIONS的主要内容,如果未能解决你的问题,请参考以下文章

IE 11 上 CORS 预检请求的奇怪问题失败

在 Angularjs 中的 IE10+ 中访问被拒绝 CORs 请求,需要跨源资源共享错误(信息?)

如何在 IE 中使用 CORS 从 https 调用 http?

获取拒绝访问错误

带有 AngularJS CORS 的 IE9、IE8 返回“访问被拒绝” - ASP.NET WebApi

浏览器 11 | Angular 4 - CORS 请求失败(XMLHttpRequest:网络错误 0x80070005,访问被拒绝。)