Lo que estoy tratando de hacer
Tengo una API web ASP.Net Core de back-end alojada en un plan gratuito de Azure (código fuente: https://github.com/killerrin/Portfolio-Backend ).
También tengo un sitio web de cliente que quiero hacer que consuma esa API. La aplicación de cliente no se alojará en Azure, sino que se alojará en páginas de Github u otro servicio de alojamiento web al que tenga acceso. Debido a esto, los nombres de dominio no se alinearán.
Al investigar esto, necesito habilitar CORS en el lado de la API web, sin embargo, he intentado casi todo durante varias horas y se niega a funcionar.
Cómo tengo la configuración del cliente Es solo un cliente simple escrito en React.js. Estoy llamando a las API a través de AJAX en Jquery. El sitio React funciona, así que sé que no es eso. La llamada a la API de Jquery funciona como lo confirmé en el intento 1. Así es como hago las llamadas
var apiUrl = "http://andrewgodfroyportfolioapi.azurewebsites.net/api/Authentication";
//alert(username + "|" + password + "|" + apiUrl);
$.ajax({
url: apiUrl,
type: "POST",
data: {
username: username,
password: password
},
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
var authenticatedUser = JSON.parse(response);
//alert("Data Loaded: " + authenticatedUser);
if (onComplete != null) {
onComplete(authenticatedUser);
}
},
error: function (xhr, status, error) {
//alert(xhr.responseText);
if (onComplete != null) {
onComplete(xhr.responseText);
}
}
});
Lo que he intentado
Intento 1 - La forma 'adecuada'
https://docs.microsoft.com/en-us/aspnet/core/security/cors
He seguido este tutorial en el sitio web de Microsoft hasta una T, probando las 3 opciones de habilitarlo globalmente en Startup.cs, configurándolo en cada controlador y probándolo en cada acción.
Siguiendo este método, Cross Domain funciona, pero solo en una sola Acción en un solo controlador (POST al AccountController). Para todo lo demás, el Microsoft.AspNetCore.Corsmiddleware se niega a configurar los encabezados.
Instalé a Microsoft.AspNetCore.Corstravés de NUGET y la versión es1.1.2
Así es como lo configuro en Startup.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add Cors
services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
// Add framework services.
services.AddMvc();
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new CorsAuthorizationFilterFactory("MyPolicy"));
});
...
...
...
}
// This method gets called by the runtime. Use this method to configure
//the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
// Enable Cors
app.UseCors("MyPolicy");
//app.UseMvcWithDefaultRoute();
app.UseMvc();
...
...
...
}
Como puede ver, estoy haciendo todo lo que me dijeron. Agregué Cors antes de MVC las dos veces, y cuando eso no funcionó, intenté poner [EnableCors("MyPolicy")]cada controlador como tal
[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class AdminController : Controller
Intento 2 - Brute forzándolo
https://andrewlock.net/adding-default-security-headers-in-asp-net-core/
Después de varias horas de intentar el intento anterior, pensé que trataría de aplicar una fuerza bruta al tratar de configurar los encabezados manualmente, obligándolos a ejecutarse en cada respuesta. Hice esto siguiendo este tutorial sobre cómo agregar encabezados manualmente a cada respuesta.
Estos son los encabezados que agregué
.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")
Estos son otros encabezados que probé que fallaron
.AddCustomHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
.AddCustomHeader("Access-Control-Allow-Headers", "content-type, accept, X-PINGOTHER")
.AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Host, User-Agent, Accept, Accept: application/json, application/json, Accept-Language, Accept-Encoding, Access-Control-Request-Method, Access-Control-Request-Headers, Origin, Connection, Content-Type, Content-Type: application/json, Authorization, Connection, Origin, Referer")
Con este método, los encabezados Cross Site se aplican correctamente y se muestran en mi consola de desarrollador y en Postman. Sin embargo, el problema es que mientras pasa el Access-Control-Allow-Origincheque, el navegador web lanza un ataque siseante (creo) Access-Control-Allow-Headersindicando415 (Unsupported Media Type)
Entonces el método de fuerza bruta tampoco funciona
Finalmente
¿Alguien ha conseguido que esto funcione y pueda echar una mano, o simplemente poder señalarme en la dirección correcta?
EDITAR
Entonces, para que las llamadas a la API se procesen, tuve que dejar de usar JQuery y cambiar a un XMLHttpRequestformato Javascript puro .
Intento 1
Me las arreglé para Microsoft.AspNetCore.Corsque funcionara siguiendo la respuesta de MindingData, excepto dentro del ConfigureMétodo que pone el app.UseCorsantes app.UseMvc.
Además, cuando se combina con la Solución API de Javascript options.AllowAnyOrigin()para el soporte comodín, comenzó a funcionar también.
Intento 2
Así que he logrado que el Intento 2 (fuerza bruta) funcione ... con la única excepción de que el comodín Access-Control-Allow-Originno funciona y, como tal, tengo que configurar manualmente los dominios que tienen acceso a él.
Obviamente no es ideal, ya que solo quiero que este WebAPI esté abierto para todos, pero al menos funciona para mí en un sitio separado, lo que significa que es un comienzo
app.UseSecurityHeadersMiddleware(new SecurityHeadersBuilder()
.AddDefaultSecurePolicy()
.AddCustomHeader("Access-Control-Allow-Origin", "http://localhost:3000")
.AddCustomHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, PATCH, DELETE")
.AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Content-Type, Authorization"));
415 (Unsupported Media Type)problema, establezca unContent-Typeencabezado de solicitud enapplication/json.