预检的 Wcf webHttpBinding 响应具有无效的 HTTP 状态代码 400

Posted

技术标签:

【中文标题】预检的 Wcf webHttpBinding 响应具有无效的 HTTP 状态代码 400【英文标题】:Wcf webHttpBinding Response for preflight has invalid HTTP status code 400 【发布时间】:2016-05-19 17:29:56 【问题描述】:

我按照 Ido Flatow 的 post 创建了一个跨域请求并创建了以下内容:

在我的服务接口上:

[OperationContract]
[WebInvoke(Method = "*", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
bool GetUserAuthentication(string userLoginName, string password);

在 app.config 上:

<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>

现在我正在使用 angular $http 服务发送一个简单的发布请求,它在 IE 和 Edge(也在 Postman)上运行,但无法在 Chrome 和 Firefox 上运行,并出现以下错误:

XMLHttpRequest 无法加载 http://localhost:5280/MetaDataService/GetUserAuthentication。回复 对于预检有无效的 HTTP 状态代码 400

Chrome 错误打印屏幕:

【问题讨论】:

【参考方案1】:

Chrome 正在预检请求以查找 CORS 标头。如果请求是可接受的,它将发送真正的请求。

我的问题是发送到我的 WCF 服务器的 OPTIONS 请求被拒绝了我为我的方法定义了Method="*",导致选项请求被定向到我的方法并期望获得参数。

基于How to handle Ajax JQUERY POST request with WCF self-host 问题的解决方案是添加新的 OperationContract 来处理 OPTIONS 请求:

[OperationContract]
[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
void GetOptions();

public void GetOptions()


此方法获取所有选项请求并允许将真正的 POST 方法定向到我的服务方法。

【讨论】:

那么你应该在 GetOptions 方法中做什么?好像是空的?【参考方案2】:

1.将此 API 添加到 IRestService(您的服务接口)

[OperationContract]
[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
void Options();

2.在RestService中实现这个功能(你的服务实现)

public void Options()

    WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
    WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
    WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type");

CORS 操作

CORS 世界中有两种类型的请求,“正常”请求和预检请求。正常请求是页面通常会向服务发出的请求,带有一个额外的标头“Origin”,它指示来源,服务可以确定是否允许来自该来源的跨域调用(通过“访问-Control-Allow-Origin”响应标头)。 “安全”请求(GET 和 HEAD)仅使用额外的标头来工作。浏览器会将 Origin 标头添加到去往页面发起域以外的域的请求中,如果服务不允许该域,则调用将失败。

“不安全”请求,例如 POST、PUT 或 DELETE,不能以同样的方式完成。如果服务不支持 CORS,它将忽略“Origin”标头并接受请求,可能会产生副作用(例如,删除记录),并且在客户端收到响应时,浏览器仍然可以“失败”的请求,但损害已经造成。在这些情况下,浏览器所做的是首先发送一个预检请求,这是一个 HTTP OPTIONS 请求,请求允许发送实际请求。如果服务响应了允许调用的请求,那么只有浏览器才会将用户请求发送到服务。

【讨论】:

以上是关于预检的 Wcf webHttpBinding 响应具有无效的 HTTP 状态代码 400的主要内容,如果未能解决你的问题,请参考以下文章

CORS WCF:对预检请求的响应未通过访问控制

从 JavaScript 访问 WCF WebService - 对预检请求的响应未通过访问控制检查

在带有 Wcf 服务的 Angular JS 的预检响应中,Access-Control-Allow-Methods 不允许方法 PUT

WCF 413 请求实体太大 - 自托管 WebHttpBinding

在 Kerberos 模式下,通过 WebHttpBinding 连接自托管 WCF 服务失败

如何使用 Microsoft JWT 令牌处理程序来保护基于 webHttpBinding 的 WCF 服务