WCF REST服务中的CORS支持

时间:2011-08-29 19:04:17

标签: c# .net wcf wcf-rest cors

我在Windows服务中托管了WCF REST服务,并且我希望每次响应都发送Access-Control-Allow-Origin HTTP标头(定义为CORS的一部分)。

我尝试的解决方案是在IDispatchMessageInspector实施中使用以下内容:

public void BeforeSendReply(ref Message reply, object correlationState)
{
    var httpResponse = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
    if (httpResponse != null)
    {
        // test of CORS
        httpResponse.Headers["Access-Control-Allow-Origin"] = "*";
    }
}

通常这会起作用,但不幸的是我的服务也使用HTTP basic authorization,这意味着当请求进入而没有Authorization标头时,WCF会自动发送401响应,要求提供凭据。不幸的是,WCF在初始交换期间没有调用我的IDispatchMessageInspector,因此Access-Control-Allow-Origin标头不会添加到初始交换中。

当我尝试从浏览器调用服务时出现问题。 CORS指定仅当源域与Access-Control-Allow-Origin响应头中列出的域匹配时才允许跨源请求(*匹配所有域)。不幸的是,当浏览器看到没有Access-Control-Allow-Origin标头的初始401响应时,它会阻止访问(根据same origin policy)。

有没有办法在WCF自动发送的初始401响应中添加标题?

4 个答案:

答案 0 :(得分:23)

这家伙救了我的一天。

http://blogs.microsoft.co.il/blogs/idof/archive/2011/07.aspx

我将把他的一些笔记放在这里,以防网页有一天死掉。 (我讨厌找到“你的答案就在这里”链接,然后链接已经死了。)

<behaviors> 
  <endpointBehaviors> 
    <behavior name="webSupport"> 
      <webHttp /> 
      <CorsSupport /> 
    </behavior> 
  </endpointBehaviors> 
</behaviors> 
<extensions> 
  <behaviorExtensions> 
    <add name="CorsSupport" type="WebHttpCors.CorsSupportBehaviorElement, WebHttpCors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
  </behaviorExtensions> 
</extensions> 
<services> 
  <service name="Service.JSonService"> 
    <endpoint address="http://localhost:8080" behaviorConfiguration="webSupport” binding="webHttpBinding" contract="Service.IJSonService" /> 
  </service> 
</services>

现在,您必须找到名为“WebHttpCors.dll”的可下载库。

但是那里有足够的(上面)可以帮助你google / bing你的解决方案。

让我循环的部分(在我的场景中)是IE正在运行,但Firefox无法正常工作。

我的原始页面是:

http://localhost:53692/test/WCFCallTestViaJQ14.htm

所以我的服务是:

http://localhost:8002/MyWCFService/MyWCFMethodByWebGet?state=NC&city=Raleigh

所以我有localhost&lt;&lt; - &gt;&gt; localhost流量。

****但是港口不同。 (53692和8002)****

IE浏览器还可以。 Firefox没用它。

然后你必须记住每个浏览器以不同方式处理他们的.Send()请求(在JQUERY中)。

现在一切都有道理。

//JavaScript snipplet from JQuery library

if (window.XMLHttpRequest) {

    returnObject = new XMLHttpRequest();

} else if (window.ActiveXObject) {

    returnObject = new ActiveXObject("Microsoft.XMLHTTP");

} else {

msg = "Your browser doesn't support AJAX!";

}

这里有一些关键词,我一直在谷歌搜索/叮咬的短语最终导致我到处。

    Result: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.statusText]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: http://localhost:53692/test/WCFCallTestViaJQ14.htm :: HandleJQueryError :: line 326" data: no]


XMLHttpRequest Send "NS_ERROR_FAILURE"

JQuery Ajax WCF Self Hosted CORS JSON

现在,你需要阅读他的博客博客,了解该守则的作用:

例如,他说:

  

“Access-Control-Allow-Origin”标头,其值为“*”

这可能是也可能不是你想要的。您可能希望更好地控制此值(标题)和其他(方法和原点)。

开发环境是一回事。 (使用你想要的所有*。)

生产是另一回事,您可能想要将这些*值调整为更具歧视性的东西。简而言之,您需要了解CORS在安全性方面实际上为您做了什么,而不仅仅是添加一个允许所有内容的行为。

  allowed-origins: '*'
  allowed-headers: '*'
  allowed-methods: '*'

答案 1 :(得分:6)

为了达到你想要的目的,你需要自己处理授权,这可以通过强制+注册HttpModule来实现...在那里你可以发出401以及你想要的任何http头...甚至还有一个样本在SO上实现 - 请参阅Adding basic HTTP auth to a WCF REST service

编辑 - 在OP评论后发表:

由于OP的评论说他是自托管的,因此解决方案不在于HTTPModule,而在于IDispatchMessageInspector.BeforeSendReplyIDispatchMessageInspector.AfterReceiveRequest

授权必须配置为“无”并在IDispatchMessageInspector中自定义实现/处理 - 这样您可以在发出401时添加任何标头。否则,处理Basic Auth的运行时不会在正确/正向验证之前调用IDispatchMessageInspector

虽然这样做有意,但这意味着您自己实施安全敏感代码,因此需要采取适当的措施来确保其正确实施......

答案 2 :(得分:0)

在WCF服务中被调用的第一个方法中添加以下行对我有用。

WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");

需要以下导入

System.ServiceModel.Web;

Refer this for original answer

答案 3 :(得分:0)

我尝试了很多方法,但是找不到任何东西,然后突然我终于知道应该仅通过OPTIONS请求发送标头,然后我发现了一些有用的SO代码here! 这完全解决了我的问题。

实际上,这里的要点是您必须在OPTIONS请求中添加标头以及仅200 OK响应,这就是在此链接上所做的事情。