CORS(跨源资源共享)https 不工作(IIS 托管 WCF 休息启用端点)

Posted

技术标签:

【中文标题】CORS(跨源资源共享)https 不工作(IIS 托管 WCF 休息启用端点)【英文标题】:CORS (Cross Origin Resource Sharing) https not working (IIS hosted WCF rest enabled endpoint) 【发布时间】:2014-11-05 05:11:17 【问题描述】:

您好,希望有人可以提供帮助

我一直在寻找通过 https 使用 CORS 到 WCF 的简单原型。我们已经实现了一个解决方案并在 http 中对其进行了测试,并且效果很好。一旦我们尝试使用 https 调用 WCF 端点,在这种情况下,我们只会得到“404 Not Found”。 但是在我们的生产代码中,我收到一个“400 Bad request”,稍后我将发布!现在我需要有关 404 错误的帮助。

我已经搜索并尝试了很多东西,但仍然无法正常工作!

我编写了一个小测试 Web 项目和 WCF 端点,可以在 http 中正常工作。

在客户端,我正在向以下端点发出 jquery ajax 请求

var theUrl = "https://myhostmachine/Cors/service.svc/web";
function makeGetDataJQueryRequest() 
    $.support.cors = true;
    $.ajax(
        url: theUrl + "/GetData?value=24",
        contentType: "application/json; charset=utf-8",
        type: "POST",
        cache: false,
        dataType: "json",
        //                data: undefined,
        success: function (response) 
            alert("success");
        ,
        error: function (a, b, c) 
            alert("error");
        
    );

在服务器上,我有我的 WCF 代码,它执行所有预检 cors 响应,正如我所说的在 http 中工作。

    我已经设置了一个自签名证书并在我的 IIS 中使用了它,同时确保通过 mmc 插件将它添加到我的证书存储中。

    当我立即发出请求时,我可以看到它没有发送 OPTIONS 请求,为什么不呢?但它确实是通过 http 发送的?

提琴手请求:

POST https://myhostmachine/Cors/service.svc/web/GetData?value=24 HTTP/1.1
Host: hsw10530.cse-servelec.com
Connection: keep-alive
Content-Length: 0
Accept: application/json, text/javascript, */*; q=0.01
Origin: https://myhostmachine
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/37.0.2062.103 Safari/537.36
Content-Type: application/json; charset=utf-8
Referer: https://hsw10530.cse-servelec.com/CorsClient/
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8
Cookie: ASPSESSIONIDCGCSARDQ=IFNPFPKAJIMFCJHEANDFOBCH

回复:

HTTP/1.1 404 Not Found
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Thu, 11 Sep 2014 09:36:51 GMT
Content-Length: 0

Web.config如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>


  <system.web>
    <compilation debug="true" />
  </system.web>

  <system.serviceModel>

    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True" />
          <serviceDebug includeExceptionDetailInFaults="True" />
        </behavior>
      </serviceBehaviors>

      <endpointBehaviors>
        <behavior name="restBehaviour">
          <webHttp />
          <CorsSupport />
        </behavior>
      </endpointBehaviors>

    </behaviors>

    <extensions>
      <behaviorExtensions>
        <add name="CorsSupport" type="WcfService.Cors.CorsSupportBehaviorElement, WcfService" />
      </behaviorExtensions>
    </extensions>

    <bindings>
      <webHttpBinding>
        <binding name="CORSWebHttpBinding" crossDomainScriptAccessEnabled="True" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          <security mode="Transport">
          </security>
        </binding>
      </webHttpBinding>
    </bindings>

    <services>
      <service name="WcfService.Service1">
        <host>
          <baseAddresses />
        </host>
        <endpoint address="" binding="wsHttpBinding" contract="WcfService.IService1" />
        <endpoint address="web" binding="webHttpBinding" bindingConfiguration="" behaviorConfiguration="restBehaviour" contract="WcfService.IService1" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>

  </system.serviceModel>

</configuration>

以下是 WCF 代码,或者至少是完成所有预检 cors 工作的重要部分。

public class CorsMessageInspector : IDispatchMessageInspector
    
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        
            HttpRequestMessageProperty httpRequest = request.Properties["httpRequest"] as HttpRequestMessageProperty;

            // Check if the client sent an "OPTIONS" request
            if (httpRequest != null)
            
                if (httpRequest.Method == "OPTIONS")
                
                    // Store the requested headers
                    OperationContext.Current.Extensions.Add(new PreflightDetected(
                        httpRequest.Headers["Access-Control-Request-Headers"]));
                
            
            return null;
        

        public void BeforeSendReply(ref Message reply, object correlationState)
        
            HttpResponseMessageProperty property = null;

            if (reply == null)
            
                // This will usually be for a preflight response
                reply = Message.CreateMessage(MessageVersion.None, null);
                property = new HttpResponseMessageProperty();
                reply.Properties[HttpResponseMessageProperty.Name] = property;
                property.StatusCode = HttpStatusCode.OK;
            
            else
            
                property = reply.Properties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty;
            

            PreflightDetected preflightRequest = OperationContext.Current.Extensions.Find<PreflightDetected>();
            if (preflightRequest != null)
            
                // Add allow HTTP headers to respond to the preflight request
                if (preflightRequest.RequestedHeaders == string.Empty)
                    property.Headers.Add("Access-Control-Allow-Headers", "Accept");
                else
                    property.Headers.Add("Access-Control-Allow-Headers", preflightRequest.RequestedHeaders + ", Accept");

                //http://hsw10530.cse-servelec.com
                property.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
            

            // Add allow-origin header to each response message, because client expects it
            property.Headers.Add("Access-Control-Allow-Origin", "*");
        
    

如果您曾经能够通过 ssl 设置 CORS,您的帮助将不胜感激,并且您做了什么来让它工作?

非常感谢 安德鲁

【问题讨论】:

【参考方案1】:

好的,我让它工作了,毕竟我只需要提供 bindingConfiguration,因为我在配置底部的端点将它作为一个空字符串

所以配置文件确实有它;我只是没有指定这一点。您还可以看到安全模式是 Transport for ssl,否则在标准 http 上应该设置为 None。

<endpoint address="web" binding="webHttpBinding" bindingConfiguration="CORSWebHttpBinding" behaviorConfiguration="restBehaviour" contract="WcfService.IService1" />

我也不需要 CORSWebHttpBinding 上的 crossDomainScriptAccessEnabled="True",因为这似乎在使用 http 时停止了它,但在 https 上没问题。

【讨论】:

以上是关于CORS(跨源资源共享)https 不工作(IIS 托管 WCF 休息启用端点)的主要内容,如果未能解决你的问题,请参考以下文章

基于 jQuery AJAX SOAP 的 Web 服务和 CORS(跨源资源共享)[关闭]

Fusion Tables 不支持 CORS(跨源资源共享)?

使用 PHP 的 CORS(跨源资源共享)

即使存在所有 CORS 标头,也存在跨源资源共享问题

python 具有跨源资源共享的瓶子(CORS)

markdown Web字体的CORS跨源资源共享问题