尽管有 web.config 条目,但带有 ASP.NET WCF 服务的 jQuery AJAX CORS 无法正常工作

Posted

技术标签:

【中文标题】尽管有 web.config 条目,但带有 ASP.NET WCF 服务的 jQuery AJAX CORS 无法正常工作【英文标题】:jQuery AJAX CORS with ASP.NET WCF service not working despite web.config entries 【发布时间】:2015-12-08 14:23:20 【问题描述】:

我试图弄清楚我的方法中缺少什么,阻止了我的 WCF 服务被访问。如果我尝试通过来自同一域的 AJAX 请求访问该服务,则没有问题。

我已经采纳了我在网站其他地方看到的建议,将其添加到 web.config 中的 <httpProtocol> 标记以启用 CORS,但它似乎不起作用(请注意前几个customHeaders 中的元素出于不同的安全原因而存在):

<location path="FooBar.svc">
    <system.webServer>
      <httpProtocol>
        <customHeaders>
          <add name="Access-Control-Request-Method" value="POST"/>
          <add name="Access-Control-Allow-Origin" value="*" />
          <add name="Access-Control-Allow-Headers" value="Content-Type, X-Requested-With, X-Custom-Header" />
        </customHeaders>
      </httpProtocol>
    </system.webServer>
  </location>

尽管这已经到位,但在尝试从单独的页面调用服务时仍然出现错误(使用 IE 开发人员工具):“XMLHttpRequest for ... required Cross Origin Resource Sharing (CORS)”

我的 jQuery ajax 调用 (Post) 也设置了用于 CORS 的值:

 crossDomain: true,
 xhrFields:  withCredentials: true ,

我什至尝试从 https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js 添加一个针对潜在 IE XDR 问题的修复程序,但没有任何效果(我使用的是 IE11,所以我不会期待它)

有人知道这里可能出了什么问题吗?

(编辑:服务本身是用这些属性设置的,如果有区别的话:

[OperationContract]
[WebInvoke(Method = "POST", 
        BodyStyle = WebMessageBodyStyle.WrappedRequest,
        ResponseFormat = WebMessageFormat.Json)]

)

(编辑 2:如果有意义,该服务必须是使用表单身份验证的全 HTTPS 站点的一部分 - 并且该服务需要使用与该站点相同的登录凭据。 )

【问题讨论】:

您是否尝试过使用类似邮递员的方式调用服务?您能在 http 响应标头中看到 Access-Control-Allow-Origin 吗? 不幸的是,我无法在我的工作机器上安装任何东西,所以我必须等待请求它的拜占庭过程完成,然后才能获得任何有用的工具(以及外面还没有服务)。我希望能在这方面有所作为。 您提到您正在使用表单身份验证。您是否为此身份验证执行了对服务的初始调用? 我没有进行初始身份验证调用。你有一个很好的链接吗?如果这是问题所在,我不会根据身份验证收到不同的错误吗? 或者不,显然在这种情况下 ASP.NET FormsAuthentication 返回 302 而不是 401 是一个已知问题......这真的很烦人 【参考方案1】:

在托管服务的后端服务器中启用 CORS 为 true 应该可以理想地解决问题。但是还有另一种方法...您可以在 jQuery 代码和 WCF 服务之间有一个包装器(注意: 这是您在没有访问权限时必须在团队中建议的方法之一修改例如 apache 中的 htaccess 文件,我们将 CORS 设置为可以访问访问我们服务的其他域)。所以方法是这样的......

jQuery Code -&gt; Wrapper (Webmethod in .NET) -&gt; WCF service

jQuery 代码和 Wrapper 位于同一个域中。 jQuery 调用 webmethod,然后调用相应的 WCF 服务方法来获取数据。这种方式的缺点是请求会多遍历一层,这也是我一开始提到Note的原因。

【讨论】:

除了 web.config 中的条目之外,是否还有其他东西可以启用 CORS?我是否必须更改 IIS 本身的内容? 查看 ViajyP 所说的 SSL。只是挑剔我遇到过类似类型的 woff 文件的不同问题,我建议发布 ssl 更改重新启动整个 IIS。【参考方案2】:

您的 &lt;customHeaders&gt; web.config 部分已针对没有凭据的 CORS 请求进行设置。您需要不同的配置来允许带有凭据的 CORS 请求:

    将额外的Access-Control-Allow-Credentials 标头设置为true

    Access-Control-Allow-Origin 标头不能设置为*。您必须为 CORS 请求源/主机返回区分大小写的匹配项。

来源:7.2 Resource Sharing Check (W3C Recommendation for Cross-Origin Resource Sharing)

【讨论】:

行为仍然没有变化【参考方案3】:

如果您的服务在 HTTPS 上并且如果您使用自签名 SSL 证书,那么跨域调用将失败,尽管为 Access-Control-Allow-Origin 标头完成了 web.config 设置。您应该尝试将 Valid SSL Certificate 导入到您的 IIS 中,看看会得到什么。

【讨论】:

为什么会这样? 这是浏览器的行为方式。这是为了避免跨站脚本 (XXS) 漏洞。为了测试目的而克服这一点;您可以尝试以下步骤: 1) 在浏览器的第一个选项卡中打开具有 Ajax 请求的跨域页面。 2) 在选项卡 2 中打开包含 WCF 服务器的网站的任何 HTTPS 页面。 3) 因为您有自签名 SSL;您应该收到带有链接的证书警告和“我了解风险...继续”消息。 4) 单击该继续链接 5) 现在再次来到具有其他域页面的选项卡 1 6) 刷新它,您的 Ajax 到 WCF 应该可以工作。在 Prod 上,您将拥有有效的 SSL。【参考方案4】:

您是否尝试过在 jquery 中使用 $.support.cors = true。

【讨论】:

抱歉,这并没有改变任何东西,至少就其本身而言。【参考方案5】:

使用 WCF,您需要做的不仅仅是在 web.config 中添加自定义标头。对于 ASP.NET Web API,只需编辑 web.config 就足够了,但如果这不是您正在处理的工作,则需要添加自定义代码以在您的 Web 服务中允许 OPTIONS 标头。基本上,您需要创建一个消息检查器,然后创建一些使用消息检查器类添加所需标头的端点行为。

有关代码和示例服务,请参阅the WCF page on enable-cors.org。

【讨论】:

在赏金用完之前现在没有机会测试这个,但这看起来是在正确的方向。 您可能还想查看 2011 年的 this blog post,因为它包含一个服务主机工厂,可以为您节省实施时间。与使用其他后端启用 CORS 相比,这确实令人头疼,但这是 100% 可能的。【参考方案6】:

已尝试在 Response 的标头中添加 Access-Control-Allow-Origin,如下所示(仅当您希望您的 WCF 服务可从任何域访问时),

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin","*");

在我的一种 Web API 方法中,我为此使用了 UrlReferrer。 代码如下所示

Uri referredURL = HttpContext.Current.Request.UrlReferrer;
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://" + referredURL.Host);

但是这种方法风险很小,因为它取决于客户端(浏览器),因此无法保证您是否会获得UrlReferrer

【讨论】:

以上是关于尽管有 web.config 条目,但带有 ASP.NET WCF 服务的 jQuery AJAX CORS 无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

asp.net、url 重写模块和 web.config

构建模式始终是调试

web.config 中的 <cors> 标记与带有自定义标头的 httpProtocol 之间有区别吗?

Resharper 无法识别 web.config 中的命名空间别名

如何使用 web.config 文件强制 HTTPS

ASP.NET WebService 仅在使用 Http Get 但 web.config 设置正确时错误地返回 XML 而不是 JSON