问题
I'm trying to enable CORS using WCF. But I get Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. The response had HTTP status code 404.
This is my Global.asax
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
This is my web.config
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="TransportSecurity">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="RESTAPI03.testAspNetAjaxBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="RESTAPI03.testAspNetAjaxBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="RESTAPI03.test">
<endpoint address="" behaviorConfiguration="RESTAPI03.testAspNetAjaxBehavior"
binding="webHttpBinding" bindingConfiguration="TransportSecurity" contract="RESTAPI03.Hotels" />
</service>
</services>
<standardEndpoints>
<webScriptEndpoint>
<standardEndpoint crossDomainScriptAccessEnabled="true"></standardEndpoint>
</webScriptEndpoint>
</standardEndpoints>
</system.serviceModel>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
<add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS" />
<add name="Access-Control-Max-Age" value="1728000" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
this is code in my application project
const httpOptions = {
headers: new HttpHeaders({
'Access-Control-Allow-Origin' : '*'
})
}
return this.httpClient.get('https://www.example/1' httpOptions ).subscribe(data => {
console.log("s");
console.log(JSON.stringify(data));
}, err => {
console.log("err => ");
console.log( JSON.stringify(err));
});
but still not working. What did I missed?
回答1:
A web application executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, or port) from its own.
CORS (Cross Origin Resource Sharing) is a way by which web browsers implement SOP (Same Origin Policy) which says that only the same origin is allowed to access a resource of the server.
Workaround: Use native http plugin. Because CORS and SOP policies are enforced by browsers only, therefore you will not get CORS errors on other http clients like native http calls and POSTman. https://ionicframework.com/docs/native/http
Why this happens:
- Suppose a login form is returned by www.example.com/login. Now, the origin becomes www.example.com
- When you will click on submit, the browser will not immediately request the server. It will first verify whether the server is taking a request from this origin ( due to SOP policy followed by browsers) by sending a preflight OPTIONS request.
- If server is allowing the request from this origin, then server will send some CORS headers including ACCESS-CONTROL-ALLOW-ORIGIN header.
Read more at: https://ionicframework.com/docs/faq/cors
- If server says yes(by sending valid CORS headers), browser will submit the form with the Origin header set to 'www.example.com' along with login parameters.
- In other cases, you may have a Login API on www.example.com/api/login server and you are sending a POST request from a different source, http://localhost in case of IONIC Apps
- Since the origin is different, you are required to set CORS headers on your Server so that any request made from the http://localhost is allowed. But there are some factors to keep in mind. Like, setting ACCESS-CONTROL-ALLOW-ORIGIN to '*' doesnot work when you send request with credentials.
I recommend that you should read this document about CORS and its policies. it will help you in the future. https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
回答2:
At first, I suspect there is something wrong with your configuration used for creating Restful style WCF service.
Pay attention to the name
property of the service section and the contract
property of the endpoint section.
<service name="RESTAPI03.test">
<endpoint address="" behaviorConfiguration="RESTAPI03.testAspNetAjaxBehavior"
binding="webHttpBinding" bindingConfiguration="TransportSecurity" contract="RESTAPI03.Hotels" />
</service>
The name
property of the service should be a qualified name of the service implemented class and the contract
property should be a qualified name of the service contract, like this.
<service name="WcfService3.Service1" behaviorConfiguration="mybehavior">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="mybinding" contract="WcfService3.IService1" behaviorConfiguration="rest"/>
</service>
Please refer to my configuration with the ProtocolMapping
feature. It works on both HTTP
and HTTPS
protocol and supports your service irrespective of any service contract.
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="httpsbinding">
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<protocolMapping>
<add binding="webHttpBinding" scheme="http"></add>
<add binding="webHttpBinding" scheme="https" bindingConfiguration="httpsbinding"/>
</protocolMapping>
</system.serviceModel>
Secondly, there usually are two ways to enable CORS
in Restful WCF service.
1. Add a global.asax
file to the WCF project and the below code
snippets to Application_BeginRequest
event.
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With,Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
- Adding a
global.asax
file and modify theApplication_BeginRequest
event.
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
Response.End();
}
Subsequently, add the following configuration to the Web.config file.
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="content-type" />
<add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
Feel free to let me know if the problem still exists.
来源:https://stackoverflow.com/questions/59943835/enable-cors-using-wcf