O que estou tentando fazer
Eu tenho uma API Web ASP.Net Core de back-end hospedada em um Plano Gratuito do Azure (código-fonte: https://github.com/killerrin/Portfolio-Backend ).
Eu também tenho um site do cliente que eu quero fazer consumir essa API. O Aplicativo Cliente não será hospedado no Azure, mas sim nas Páginas do Github ou em outro Serviço de Hospedagem da Web ao qual tenho acesso. Por esse motivo, os nomes de domínio não se alinham.
Analisando isso, preciso habilitar o CORS no lado da API da Web, no entanto, tentei quase tudo por várias horas e agora ele se recusa a trabalhar.
Como eu tenho a configuração do cliente É apenas um cliente simples escrito em React.js. Estou chamando as APIs através do AJAX no Jquery. O site React funciona, então eu sei que não é isso. A chamada da API do Jquery funciona como eu confirmei na tentativa 1. Aqui está como eu faço as chamadas
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);
}
}
});
O que eu tentei
Tentativa 1 - O caminho 'adequado'
https://docs.microsoft.com/en-us/aspnet/core/security/cors
Eu segui este tutorial no site da Microsoft até um T, tentando todas as 3 opções de ativá-lo globalmente no Startup.cs, configurando-o em todos os controladores e testando-o em todas as ações.
Seguindo esse método, o domínio cruzado funciona, mas apenas em uma única ação em um único controlador (POST para o AccountController). Para todo o resto, o Microsoft.AspNetCore.Cors
middleware se recusa a definir os cabeçalhos.
Eu instalei Microsoft.AspNetCore.Cors
através do NUGET e a versão é1.1.2
Aqui está como eu o configurei no 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 você pode ver, estou fazendo tudo o que foi dito. Eu adiciono Cors antes do MVC as duas vezes e, quando isso não funcionou, tentei colocar [EnableCors("MyPolicy")]
todos os controladores assim
[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class AdminController : Controller
Tentativa 2 - Brute Forçando-o
https://andrewlock.net/adding-default-security-headers-in-asp-net-core/
Depois de várias horas tentando a tentativa anterior, imaginei que tentaria forçá-la tentando definir os cabeçalhos manualmente, forçando-os a executar todas as respostas. Fiz isso seguindo este tutorial sobre como adicionar cabeçalhos manualmente a todas as respostas.
Estes são os cabeçalhos que adicionei
.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")
Estes são outros cabeçalhos que tentei que falharam
.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")
Com esse método, os cabeçalhos entre sites estão sendo aplicados corretamente e são exibidos no meu console do desenvolvedor e no Postman. O problema, no entanto, é que, enquanto passa na Access-Control-Allow-Origin
verificação, o navegador da web lança um chiado (acredito) Access-Control-Allow-Headers
afirmando415 (Unsupported Media Type)
Portanto, o método da força bruta também não funciona
Finalmente
Alguém conseguiu que isso funcionasse e poderia dar uma mãozinha ou apenas ser capaz de me apontar na direção certa?
EDITAR
Portanto, para obter as chamadas da API, tive que parar de usar o JQuery e mudar para o XMLHttpRequest
formato Javascript puro .
Tentativa 1
Eu consegui fazer o Microsoft.AspNetCore.Cors
trabalho seguindo a resposta de MindingData, exceto dentro do Configure
método colocando o app.UseCors
antes app.UseMvc
.
Além disso, quando combinado com a solução da API Javascript options.AllowAnyOrigin()
para suporte a caracteres curinga começou a funcionar também.
Tentativa 2
Então, eu consegui fazer com que a Tentativa 2 (força bruta) funcione ... com a única exceção de que o curinga Access-Control-Allow-Origin
não funciona e, como tal, tenho que definir manualmente os domínios que têm acesso a ela.
Obviamente, não é o ideal, pois eu só quero que essa WebAPI seja aberta a todos, mas pelo menos funciona para mim em um site separado, o que significa que é um começo
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, defina umContent-Type
cabeçalho de solicitação comoapplication/json
.