What I´m trying to do is to enable CORS (Cross-origin Resource Sharing) for .net MVC 5 Azure website when calling a https service (not my own) from my JavaScript.
I always get the same error
XMLHttpRequest cannot load https://someservice-I-have-no-control-over. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://my.azurewebsites.net' is therefore not allowed access. The response had HTTP status code 400.
I have managed to enable this when developing locally, setting my project to https and adding the following to web.config
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS"/>
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept, SOAPAction"/>
<add name="Access-Control-Max-Age" value="1728000"/>
</customHeaders>
</httpProtocol>
</system.webServer>
That adds the 'Access-Control-Allow-Origin' header. But that does not seem to work on the Azure website.
And I can´t find any settings like in the Mobile Services where you can allow this like you see here.
Since I know you are all going to ask for code (that works locally btw) there you have the simple Jquery call to the service
$.ajax({
url: 'https://someservice-I-have-no-control-over',
dataType: 'json',
contentType: 'application/json',
type: 'GET',
success: function (response) {
$.each(response, function (key, value) {
console.log("success"); //Doesn´t happen! :-(
});
},
error: function (xhr, text, error) {
if ($.isFunction(onError)) {
onError(xhr.responseJSON);
}
}
});
So any thoughts?
Edit 1
Just to clarify a little.
I am calling a service that I have no control over that is a https one, in a javascript (not a controller) that is mine.
Edit 2
Ok I thought that I could intercept the response from the third party service and add this header before the browser rejects it. As I see it that is not possible (right?). But how come it works locally?
If I capture the call to this service with e.g LiveHTTPHeaders I get the following response where there is not a "Access-Control-Allow-Origin" restriction (so way does it work locally?).
Request (to https://someservice-I-have-no-control-over.com)
GET /someservice-I-have-no-control-over/SomeAction/44 HTTP/1.1
Host: someservice-I-have-no-control-over.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
If-None-Match: "53867cff-96b0-411f-88b7-d84765f9f8e8"
Cache-Control: max-age=0
Reply
HTTP/1.1 304 Not Modified
Cache-Control: max-age=900
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Date: Tue, 24 Feb 2015 11:06:53 GMT
Not possible.
It works locally because it's the server that must have the allow headers, and when you call your own webserver from your javascript you can add those headers.
When you call the real website they do probably not add the CORS allow header (Access-Control-Allow-Origin) and your request is therefore denied.
What you could do is either to use JSONP or proxy all requests through your own website.
You could for instance use my CORS proxy: https://github.com/jgauffin/corsproxy. It's intended usage is for IE9 and below, but works just as fine for all requests.
WebApiConfig I set it the WebApiConfig class and it worked. I also had issues on Azurewebsites when trying to set it via web.config.
Try this in WebApiConfig:
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
You can edit the "", "", "*" if you don't want to allow everything.
If you're using Owin, you can do this in the Startup.cs file:
app.UseCors(CorsOptions.AllowAll);
Use this if and only if you intentionally plan to expose your API to all origins and headers.
Else, you can try it this way by decorating your controller or specific methods:
[EnableCors(origins: "http://someCallingService", headers: "*", methods: "*")]
Check out THIS article
I addressed this by installing the following package:
Microsoft.AspNet.WebApi.Cors
...then using the Config.EnableCors() as described above and altering my web.config transform:
In WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Continue configuration as you wish...
}
Then, in the web.config transform, in my case named web.PPE.config because it's for Pre-Production:
<system.webServer>
<httpProtocol>
<!-- custom headers necessary for CORS -->
<customHeaders xdt:Transform="Replace">
<clear /> <!-- the clear here is important! -->
<add name="Access-Control-Allow-Origin" value="http://url-that-is-allowed-to-communicate-with-this-server.com" />
<!-- must match server DNS address or SignalR can't communicate with Hub remotely -->
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
</system.webServer>
YMMV on whether to include the Allow-Credentials option. I found that necessary with my need, which was to enable access to a SignalR hub on a remote Azure webserver/app instance.
Good luck!
Related
I use signalR in asp.net mvc for web api and I need to enable cors in web.config.
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, HEAD, OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true"/>
<add name="Access-Control-Allow-Headers" value="X-Requested-With, origin, content-type, accept" />
But when I'm going to connect to signalR, it displays the following error:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include
Follows the code to the startup.cs:
[EnableCors("CorsPolicy")]
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
How can I fix it?
As your error says:
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'.
And you have:
<add name="Access-Control-Allow-Origin" value="*" />
So in this case you should provide the origin from where you are connecting. If you are trying to connect from the front-end you can use this as an example:
<add name="Access-Control-Allow-Origin" value="https://localhost:4200"/>
Headers received through preflight options call:
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: POST
Access-Control-Allow-Origin: *
Allow: POST,OPTIONS
Still the error:
Access to XMLHttpRequest at 'http://192.168.29.7/rest/api/login' from
origin 'http://localhost:8080' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
Backend: IIS,
Frontend: Vue (Axios):
return axios
.post('//192.168.29.7/rest/api/expenseAPI/login',credentials, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.then(({ data }) => {
...
})
Please help.
try to install the cors module in iis and set the below code in web.config file:
<system.webServer>
<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" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
</system.webServer>
https://www.iis.net/downloads/microsoft/iis-cors-module
Usually, CORS is not a frontEnd issue if you're using nodejs in the backEnd try to use CROS middleware if you're using Laravel you can make a middleware that returns
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Origin: *
PS defaults header is axios is Content-Type: application/json you don't have to write that
I’m trying to remove the response Server header from an Azure Web App ( with an ASP Net core application )
After many tries of changing the web.config and removing the header in app code using a middleware, Microsoft doesn’t give up and set the response header to Server: Microsoft-IIS/10.0 :)
The problem appears only when I’m trying to access the server on http (not https). Response code from the server is 301, and this is the only response that has the Server header.
Checking the logs I was not able to find any request to http://, and perhaps this is why I’m not able to remove header, because the request is not process in my application code.
A solution that I’m thinking is to disable the azure HTTPS only and do the redirect to https in my code (I tested and is working - server header is removed)
Is there another workaround without disabling the HTTPS only option?
Here is what I tried
Startup.cs
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
context.Response.Headers.Add("server", string.Empty)
}
app.UseHttpsRedirection();
}
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<httpRuntime enableVersionHeader="false" />
<!-- Removes ASP.NET version header. -->
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="Server" />
<remove name="X-Powered-By" />
</customHeaders>
<redirectHeaders>
<clear />
</redirectHeaders>
</httpProtocol>
<security>
<requestFiltering removeServerHeader="true" />
<!-- Removes Server header in IIS10 or later and also in Azure Web Apps -->
</security>
<rewrite>
<outboundRules>
<rule name="Change Server Header"> <!-- if you're not removing it completely -->
<match serverVariable="RESPONSE_Server" pattern=".+" />
<action type="Rewrite" value="Unknown" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
UPDATE
When the URL of http:// is requested, IIS will process it, this time without code. So we can't control it by the code, we can only set it on the server, such as some scripts or tools. But on Azure, we have no way to directly operate as a physical server, so after exploration, I suggest that Front Door can be used to deal with this problem. Hiding server information through proxy should be a better way.
After my test, the server information is hidden, you can refer to this document . We can see from the picture that there is no 301 redirect request, and no server information in other requests.
PREVIOUS
You need to modify Global.asax.cs and Web.config file in your program.
In Global.asax.cs.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
MvcHandler.DisableMvcResponseHeader = true;
PreSendRequestHeaders += Application_PreSendRequestHeaders;
}
protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
//HttpContext.Current.Response.Headers.Remove("Server");
HttpContext.Current.Response.Headers.Set("Server","N/A");
}
}
And In Web.config.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" >
</modules>
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>
</system.webServer>
Then u can deploy your app. After the above code modification, access to the interface or static resources can see that the server information is modified, of course, it can also be deleted by Remove.
You also can handle special event by http status code.
protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
//HttpContext.Current.Response.Headers.Remove("Server");
int StatusCode= HttpContext.Current.Response.StatusCode;
// handle like http status code 301
HttpContext.Current.Response.Headers.Set("Server","N/A");
}
I have installed IIS CORS moudule on the server.
On the OPTIONS request I get :
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE
Access-Control-Allow-Origin: ### the actual good origin ###
Date: Fri, 13 Sep 2019 06:32:11 GMT
Server: Microsoft-IIS/10.0
Vary: Origin
X-Powered-By: ASP.NET
But on the POST request I get
Access-Control-Allow-Origin: http://localhost/
Content-Length: 1216
Content-Type: application/json; charset=utf-8
Date: Fri, 13 Sep 2019 06:32:11 GMT
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
In web config i have
<cors enabled="true">
<add origin="### the actual good origin ###" allowCredentials="true" >
<allowHeaders allowAllRequestedHeaders="true" />
<allowMethods >
<add method="GET" />
<add method="HEAD" />
<add method="POST" />
<add method="PUT" />
<add method="DELETE" />
</allowMethods>
</add>
</cors>
The WebService I try to call is an WCF webservice.
How can I disable the "localhost" header on the POST request?
I am not setting anything static header, neither in web.config nor in IIS itself
I suggest you try to add the Global.asax file to the WCF project, which is used to solve the CORS issue.
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();
}
Alternatively, we could also configure it in webconfig file.
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
Response.End();
}
}
Webconfig.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" />
<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.
I have an MVC application which also uses webapi2.
To call the api services i am using jquery ajax as below.
$.ajax({
url: GetBaseURL() + '/api/MyController/PutMethod',
type: 'put',
data: dataObject,
contentType: 'application/json',
timeout: AJAX_TIMEOUT,
success: function () {
self.CallOtherFunction();
});
And the function getbaseURL returns content.url("~")
While this approach is working out from some pages, it's throwing the "Cross Origin Request Blocked : The same origin policy disallows reading the remote resource at http://api/MyController/PutMethod" error.
I have tried googling out on cors but could not understand why I am facing this error, even though I have both MVC and Webapi under one solution, running through visual studio.
Help appreciated.
Thanks.
The problem is in your WebApi. The projects could be in the same solution and only the port could be different and you would get the CORS error. To solve the WebApi problem you can read this article: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
if you facing this error while calling of an api in mvc then you follow the below steps
Step 1 :put this tags in your web.config file in api under the system.webServer tag.
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Content-Type, X-Your-Extra-Header-Key"/>
<add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS"/>
<add name="Access-Control-Allow-Credentials" value="true"/>
</customHeaders>
</httpProtocol>
</system.webServer>
Step 2- put this in gloabl.asax.cs file in your webapi application
protected void Application_BeginRequest()
{
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
Response.End();
Response.Flush();
}
}