CORS自定义程序不起作用405方法不允许

时间:2018-02-05 09:51:38

标签: javascript c# web-services wcf cors

有一个用C#编写的WCF Web服务有两个端点(SOAP + rest)。两种服务都需要一个名为“token”的自定义头字段。此自定义标头无法通过javascript代码发送。响应为 405 Method Not Allowed 。这是跨平台原点问题的错误。

我已经找了一些解决方案,但没有任何效果。我尝试通过在我的localhost环境中尝试一些代码snipets来解决问题。

这是我的localhost webservice的web.config:

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>

  <system.web>
    <compilation debug="true" targetFramework="4.5.1" />
    <httpRuntime targetFramework="4.5.1"/>
    <customErrors mode="Off"/>
  </system.web>

  <system.runtime.caching>
    <memoryCache>
      <namedCaches>
        <add name="Default" physicalMemoryLimitPercentage="10" cacheMemoryLimitMegabytes="128" />
      </namedCaches>
    </memoryCache>
  </system.runtime.caching>

  <system.serviceModel>

    <services>
      <service name="MyProject.TokenTestService.Service" 
               behaviorConfiguration="ServiceAuthBehaviorHttp"
               >      
       <endpoint address=""
                  binding="basicHttpBinding"
                  bindingConfiguration="BasicHttpBindingLocalhost"
                  contract="MyProject.TokenTestService.IService"
                  />
        <endpoint address="rest"
                  behaviorConfiguration="AjaxEnabledBehavior"
                  binding="webHttpBinding"
                  bindingConfiguration="webBindingLocalhost"
                  contract="MyProject.TokenTestService.IService"
                  />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>

    <behaviors>

      <endpointBehaviors>
        <behavior name="AjaxEnabledBehavior">
          <webHttp helpEnabled="true" />
        </behavior>
      </endpointBehaviors>

      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>

        <behavior name="ServiceAuthBehaviorHttp">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <TokenValidationServiceExtension ApplicationId="2" CachingTimeInSeconds="3600"  />
        </behavior>
      </serviceBehaviors>

    </behaviors>

    <extensions>
      <behaviorExtensions>
        <add 
            name="TokenValidationServiceExtension" 
            type="MyProject.Authentication.Common.Extensions.TokenValidationServiceBehaviorExtension, MyProject.Authentication.Common" />
      </behaviorExtensions>
    </extensions>

    <bindings>
      <basicHttpBinding>

            <binding name="BasicHttpBinding_IAuthServiceSoap">
              <security mode="Transport" />
            </binding>

        <binding name="BasicHttpBinding_IAuthServiceSoapLocalhost" />

        <binding name="BasicHttpBindingLocalhost" />

      </basicHttpBinding>

      <webHttpBinding>
        <binding name="webBindingLocalhost" crossDomainScriptAccessEnabled="true" />
      </webHttpBinding>
    </bindings>

    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>

    <httpProtocol>
      <customHeaders>
        <add name="Origin" value="localhost" />
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS" />
        <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept, Token, ApplicationPriviliges" />
        <add name="Access-Control-Max-Age" value="1728000" />
      </customHeaders>
    </httpProtocol>

  </system.webServer>

</configuration>

这是javascript代码:

<script>
$.ajax({
  url: "http://localhost:14305/Service.svc/rest/GetDataAdmin",
  type: "GET",
  crossDomain: true,
  dataType: 'json',
  data: null,
  headers: {
            'Content-Type':'application/json; charset=utf-8',
            'Token':'3C6E27D9-ACA7-47D9-BB8B-1C960813D79C'
  },
  success: function( result ) {
    $( "Result:" ).html( "<strong>" + result + "</strong>" );
  },
  error: function( err ) {
    $( "Result:" ).html( "<strong>" + err + "</strong>" );
  }
});
</script>

在请求服务后,我在响应中获取自定义标头(token,ApplicationPriviliges):

    Cache-Control: private
Allow: GET
Content-Type: text/html; charset=UTF-8
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcVEZTXEdJVFxMaWZiaS5BcGkuQXV0aGVudGljYXRpb24uVGVzdFNlcnZpY2VcTGlmYmkuQXBpLlRva2VuVGVzdFNlcnZpY2VcU2VydmljZS5zdmNccmVzdFxHZXREYXRhQWRtaW4=?=
X-Powered-By: ASP.NET
Origin: localhost
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Token, ApplicationPriviliges
Access-Control-Max-Age: 1728000
Date: Mon, 05 Feb 2018 09:48:55 GMT
Content-Length: 1766

我找到的最佳解决方案是在网络服务器的配置中设置customHeaders。但我不适合我。

有人有想法吗?

非常感谢!

1 个答案:

答案 0 :(得分:0)

您收到不允许的405方法,因为您的请求包含导致预检请求的标题令牌。预检请求使用OPTIONS方法,显然您的服务不允许使用此方法。

向web.config添加customHeaders不足以使Preflight请求正常工作。服务器必须返回一个空体响应,其中包含一堆标题,告诉浏览器允许哪些内容。

幸运的是,IIS Team已经发布了IIS CORS模块,允许您在web.config中以声明方式配置CORS。例如:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <cors enabled="true" failUnlistedOrigins="true">
            <add origin="*" />
            <add origin="https://*.microsoft.com"
                 allowCredentials="true"
                 maxAge="120"> 
                <allowHeaders allowAllRequestedHeaders="true">
                    <add header="header1" />
                    <add header="header2" />
                </allowHeaders>
                <allowMethods>
                     <add method="DELETE" />
                </allowMethods>
                <exposeHeaders>
                    <add header="header1" />
                    <add header="header2" />
                </exposeHeaders>
            </add>
            <add origin="http://*" allowed="false" />
        </cors>
    </system.webServer>
</configuration>

Here您有introduction to IIS CORS Module.

您可以从here

下载

here是文档。

不幸的是,完整的IIS不适用于IIS Express。但是,您可以将Visual Studio解决方案配置为使用本地IIS。您必须安装它并以管理员身份执行Visual Studio,但它会起作用。