有一个用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
我找到的最佳解决方案是在Web服务器的配置中设置customHeaders。但我不适合我。
有人有想法吗?
非常感谢你!
您收到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,但它会起作用。