Origin header, the server must respond using the Access-Control-Allow-Origin header. Example of request / response pair from address foo.example foo.example on service bar.other/resources/public-data bar.other/resources/public-data :Request:
GET / resources / public-data / HTTP / 1.1
Host: bar.other
Origin:foo.example
[Other headers]
Answer:
HTTP / 1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Access-Control-Allow-Origin: *
Content-Type: application / xml
')
[XML Data]
Access-Control-Allow-Origin - this header defines the resources from which requests may come. Can be used * or a specific domain, for example foo.example foo.example . This header can be only one, and can contain only one value, i.e. domain list can not be set.Access-Control-Allow-Methods - this header defines which methods can be used to communicate with the server. We confine ourselves to the following: POST,GET,OPTIONS , but you can also use PUT , and DELETE , and others.Access-Control-Allow-Headers — This header defines the list of available headers. For example, Content-Type , which allows you to specify the type of application/json response.Access-Control-Allow-Credentials — This header determines whether the transfer of cookies and authorization is allowed. Possible values are true and false . Important: the data will be transmitted only if a specific domain is explicitly set up in the Access-Control-Allow-Origin header, if you use * , the header will be ignored and the data will not be transmitted.Access-Control-Allow-Headers returns, or to the server, unless Access-Control-Allow-Credentials and the correct Access-Control-Allow-Origin . Before a POST request to another domain, the browser will first make an OPTIONS request ( preflight request ) for information on the allowed methods of working with the service. <system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="http://foo.example" /> <add name="Access-Control-Allow-Headers" value="Content-Type" /> <add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" /> <add name="Access-Control-Allow-Credentials" value="true" /> </customHeaders> </httpProtocol> </system.webServer> protected void Application_BeginRequest(object sender, EventArgs e) { var allowedOrigins = new [] { "http://foo.example", "http://bar.example" }; var request = HttpContext.Current.Request; var response = HttpContext.Current.Response; var origin = request.Headers["Origin"]; if (origin != null && allowedOrigins.Any(x => x == origin)) { response.AddHeader("Access-Control-Allow-Origin", origin); response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); response.AddHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With"); response.AddHeader("Access-Control-Allow-Credentials", "true"); if (request.HttpMethod == "OPTIONS") { response.End(); } } } [ServiceContract] public class MyService { [OperationContract] [WebInvoke(Method = "POST", ...)] public string DoStuff() { AddCorsHeaders(); return "<Data>"; } private void AddCorsHeaders() { var allowedOrigins = new [] { "http://foo.example", "http://bar.example" }; var request = WebOperationContext.Current.IncomingRequest; var response = WebOperationContext.Current.OutgoingResponse; var origin = request.Headers["Origin"]; if (origin != null && allowedOrigins.Any(x => x == origin)) { response.AddHeader("Access-Control-Allow-Origin", origin); response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); response.AddHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With"); response.AddHeader("Access-Control-Allow-Credentials", "true"); if (request.HttpMethod == "OPTIONS") { response.End(); } } } } AddCorsHeaders call AddCorsHeaders required in each service method. Plus - ease of use.EnableCorsBehavior are created: using System; using System.ServiceModel.Channels; using System.ServiceModel.Configuration; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; namespace My.Web.Cors { public class EnableCorsBehavior : BehaviorExtensionElement, IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new EnableCorsMessageInspector()); } public void Validate(ServiceEndpoint endpoint) { } public override Type BehaviorType { get { return typeof(EnableCorsBehavior); } } protected override object CreateBehavior() { return new EnableCorsBehavior(); } } } EnableCorsMessageInspector : using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Dispatcher; namespace My.Web.Cors { public class EnableCorsMessageInspector : IDispatchMessageInspector { public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { var allowedOrigins = new [] { "http://foo.example", "http://bar.example" }; var httpProp = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name]; if (httpProp != null) { string origin = httpProp.Headers["Origin"]; if (origin != null && allowedOrigins.Any(x => x == origin)) { return origin; } } return null; } public void BeforeSendReply(ref Message reply, object correlationState) { string origin = correlationState as string; if (origin != null) { HttpResponseMessageProperty httpProp = null; if (reply.Properties.ContainsKey(HttpResponseMessageProperty.Name)) { httpProp = (HttpResponseMessageProperty)reply.Properties[HttpResponseMessageProperty.Name]; } else { httpProp = new HttpResponseMessageProperty(); reply.Properties.Add(HttpResponseMessageProperty.Name, httpProp); } httpProp.Headers.Add("Access-Control-Allow-Origin", origin); httpProp.Headers.Add("Access-Control-Allow-Credentials", "true"); httpProp.Headers.Add("Access-Control-Request-Method", "POST,GET,OPTIONS"); httpProp.Headers.Add("Access-Control-Allow-Headers", "X-Requested-With,Content-Type"); } } } } web.config created by EnableCorsBehavior : <system.serviceModel> ... <extensions> <behaviorExtensions> <add name="crossOriginResourceSharingBehavior" type="My.Web.Cors.EnableCorsBehavior, My.Web, Version=1.0.0.0, Culture=neutral" /> </behaviorExtensions> </extensions> ... </system.serviceModel> EnableCorsBehavior to the Behavior configuration of our Endpoint 'a <system.serviceModel> <services> <service name="My.Web.Services.MyService"> <endpoint address="" behaviorConfiguration="My.Web.Services.MyService" binding="webHttpBinding" contract="My.Web.Services.MyService" /> </service> </services> ... <behaviors> ... <endpointBehaviors> ... <behavior name="My.Web.Services.MyService"> <webHttp/> <crossOriginResourceSharingBehavior /> <!-- --> </behavior> ... </endpointBehaviors> ... </behaviors> ... </system.serviceModel> OPTIONS method. In my case, I used the simplest option: the OPTIONS request handler method is added to the service body. [OperationContract] [WebInvoke(Method = "OPTIONS", UriTemplate = "*")] public void GetOptions() { // EnableCorsMessageInspector } GetOptions method to the service body and a considerable amount of additional code. On the other hand, this approach allows almost completely separating the logic of the service and the logic of communication.withCredentials flag is set to true withCredentials flag. I think that many people use jQuery to work with AJAX, so I’ll give an example for it: $.ajax({ type: 'POST', cache: false, dataType: 'json', xhrFields: { withCredentials: true }, contentType: 'application/json; charset=utf-8', url: options.serviceUrl + '/DoStuff' }); bar.other bar.other , we have the ability to return user data for an Ajax request from the site foo.example foo.example . In my case, this was used to enable the user to receive notifications and respond to events, being on one of the sites living within the same business project, but located on different domains and platforms. As mentioned above, the key points here are the header Access-Control-Allow-Credentials and setting the flag for XmlHttpRequest withCredentials=true .Source: https://habr.com/ru/post/219895/
All Articles