Cannot POST for class IHTTPHandler, origin is not allowed Access-Control-Allow-Origin

I have a C # SOAP web service, as well as some IHTTPHandler custom classes deployed to https://localhost:123 . I have an HTML page at http://localhost trying to use jQuery to send an AJAX POST request to one of these handlers. I get the following every time:

XMLHttpRequest cannot load https://localhost:123/(S(the_session_id))/MyHandler.ashx . The origin of http://localhost not valid with Access-Control-Allow-Origin.

I tried to create the CrossOriginModule module and the CrossOriginHandler handler, as in this question , updating my web.config as they suggest. I tried to add context.Response.AppendHeader("Access-Control-Allow-Headers", "x-requested-with"); to my ProcessRequest handler as suggested in this question . I tried the following steps in this blog post about adding OPTIONS to SimpleHandlerFactory-Integrated-4.0 in system.webServer / handlers on the web. configurations. Nothing helps.

Here is my ProcessRequest handler:

  public void ProcessRequest(HttpContext context) { context.Response.ContentType = "application/json"; context.Response.AppendHeader("Access-Control-Allow-Origin", "*"); context.Response.AppendHeader("Access-Control-Allow-Headers", "x-requested-with"); context.Response.Write( /* some JSON string */ ); } 

Here is the relevant section of my web.config:

 <system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> </customHeaders> </httpProtocol> <modules runAllManagedModulesForAllRequests="true"> <add name="CrossOriginModule" preCondition="managedHandler" type="MyNamespace.CrossOriginModule, MyNamespace, Version=1.0.0.0, Culture=neutral" /> </modules> <handlers> <add name="CrossOrigin" verb="OPTIONS" path="*" type="MyNamespace.CrossOriginHandler, MyNamespace, Version=1.0.0.0, Culture=neutral" /> <remove name="SimpleHandlerFactory-Integrated-4.0" /> <add name="SimpleHandlerFactory-Integrated-4.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG,OPTIONS" type="System.Web.UI.SimpleHandlerFactory" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" /> <add name="MyHandler" verb="*" path="MyHandler.ashx" type="MyNamespace.MyHandler, MyNamespace, Version=1.0.0.0, Culture=neutral" /> </handlers> </system.webServer> 

Using jQuery 1.7.2, here is how I make a query for my handler:

 $.ajax({ url: url, data: {user: userName, pass: password}, type: 'POST', dataType: 'json', success: function(data, textStatus, jqXHR) { ... } }); 

I also do not use cookies for sessions on the server, so <sessionState cookieless="true" /> is in my web.config, if that matters. My server is IIS 7.5.

I can use JSONP for most requests because I do not pass sensitive data in the url. However, for this handler, I need to do a regular POST, as it involves sending the password in clear text. It is over SSL, but this post recommends that you do not send sensitive data to the URL, even through SSL. Therefore, I need to make a POST request through AJAX to the https URL and return the JSON, and the requesting page will not be on the same host as the server.

Edit: some other things I tried:

Modifying the web.config httpProtocol :

 <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Methods" value="OPTIONS,POST,GET"/> <add name="Access-Control-Allow-Headers" value="x-requested-with"/> <add name="Access-Control-Allow-Origin" value="*" /><!-- Also tried http://localhost --> </customHeaders> </httpProtocol> 

I added context.Response.AppendHeader("Access-Control-Allow-Methods", "POST"); in ProcessRequest . I also tried context.Response.AppendHeader("Access-Control-Allow-Methods", "POST,OPTIONS"); and changed the jQuery ajax settings to include contentType: 'application/json' , which forces him to make an OPTIONS request instead of POST - this still fails.

Should I list all my custom IHTTPHandler classes in web.config in <handlers> ? I now have MyHandler , with its verb="*" , but it does not seem to help.

Edit: so another oddity. It seems that my request actually goes on the server side when I send a POST message to its output, but the browser acts as if it was rejected, but still tells me that "localhost not allowed" is not specified. Therefore, my AJAX POST for the server authenticates me as I want, but the browser canceled the request and the error appears in the Chrome console, so my success event handler does not start.

+4
source share
2 answers

The ProcessRequest handler should also set the following header:

 Access-Control-Allow-Methods: POST 

(Basically, this header should be set in the OPTIONS response along with the Access-Control-Allow-Headers response header).

+3
source

This is stupid, and I'm not sure what is happening, but my POST passes, my authentication happens on the server, but the browser thinks this is not allowed, so it fails. I already had a JSONP-enabled handler that will determine if the session is active and the user is authenticated, so I changed the AJAX call to the following:

 $.ajax({ url: url, data: {user: userName, pass: password}, type: 'POST', dataType: 'json', complete: function(jqXHR, textStatus) { checkIfAuthenticated( function() { // authenticated onComplete(true, null) }, function() { // not authenticated onComplete(false, textStatus); } ); } }); 

So I still have "XMLHttpRequest cannot load https://.../AuthHandler.ashx . The error" Start " http://localhost not resolved by the error Access-Control-Allow-Origin" on my Chrome console, and the Network tab in Chrome still shows the POST request canceled. I need to make an additional request here, via the checkIfAuthenticated function, to check if the authentication was unsuccessful or not, but it works.

My ProcessRequest on the server in MyHandler as follows:

 public void ProcessRequest(HttpContext context) { context.Response.ClearHeaders(); string origin = context.Request.Headers["Origin"]; context.Response.AppendHeader("Access-Control-Allow-Origin", string.IsNullOrEmpty(origin) ? "*" : origin); string requestHeaders = context.Request.Headers["Access-Control-Request-Headers"]; context.Response.AppendHeader("Access-Control-Allow-Headers", string.IsNullOrEmpty(requestHeaders) ? "*" : requestHeaders); context.Response.AppendHeader("Access-Control-Allow-Methods", "POST, OPTIONS"); context.Response.ContentType = "application/json"; context.Response.Write(/* JSON response */); context.Response.Flush(); } 

And here is what the corresponding section of my web.config looked like:

  <system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Methods" value="OPTIONS,POST,GET"/> <add name="Access-Control-Allow-Headers" value="x-requested-with"/> <add name="Access-Control-Allow-Origin" value="*" /> </customHeaders> </httpProtocol> <handlers> <add name="MyHandler" verb="*" path="MyHandler.ashx" type="MyNamespace.MyHandler, MyNamespace, Version=1.0.0.0, Culture=neutral" /> </handlers> </system.webServer> 

I would prefer a solution that convinces my browser that the request is indeed resolved, because it is a stupid workaround.

0
source

All Articles