Co próbuję zrobić
Mam backend ASP.Net Core Web API hostowany na bezpłatnym abonamencie Azure (kod źródłowy: https://github.com/killerrin/Portfolio-Backend ).
Mam również witrynę kliencką, którą chcę używać w tym interfejsie API. Aplikacja kliencka nie będzie hostowana na platformie Azure, ale raczej będzie hostowana na stronach Github lub w innej usłudze hostingowej, do której mam dostęp. Z tego powodu nazwy domen nie będą się zgadzać.
Patrząc na to, muszę włączyć CORS po stronie Web API, jednak próbowałem już prawie wszystkiego od kilku godzin i to nie działa.
Jak mam skonfigurować klienta To tylko prosty klient napisany w React.js. Dzwonię do interfejsów API przez AJAX w Jquery. Strona React działa, więc wiem, że to nie to. Wywołanie interfejsu API Jquery działa tak, jak zostało to potwierdzone w Próbie 1. Oto jak wykonuję połączenia
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);
}
}
});
Co próbowałem
Próba 1 - „Właściwa” droga
https://docs.microsoft.com/en-us/aspnet/core/security/cors
Wykonałem ten samouczek na stronie Microsoft do T, wypróbowując wszystkie 3 opcje włączania go Globalnie w pliku Startup.cs, konfigurowania go na każdym kontrolerze i wypróbowania go przy każdej akcji.
Zgodnie z tą metodą Cross Domain działa, ale tylko na pojedynczej akcji na jednym kontrolerze (POST do AccountController). W pozostałych przypadkach Microsoft.AspNetCore.Cors
oprogramowanie pośrednie odmawia ustawienia nagłówków.
Zainstalowałem Microsoft.AspNetCore.Cors
przez NUGET, a wersja jest1.1.2
Oto jak mam to skonfigurować w 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();
...
...
...
}
Jak widać, robię wszystko zgodnie z zaleceniami. Dwa razy dodawałem Corsę przed MVC, a kiedy to nie działało, próbowałem nałożyć [EnableCors("MyPolicy")]
każdy kontroler jako taki
[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class AdminController : Controller
Próba 2 - brutalne zmuszanie
https://andrewlock.net/adding-default-security-headers-in-asp-net-core/
Po kilku godzinach próbowania poprzedniej próby, doszedłem do wniosku, że spróbuję go przerobić, próbując ręcznie ustawić nagłówki, zmuszając je do uruchomienia przy każdej odpowiedzi. Zrobiłem to po tym samouczku, w jaki sposób ręcznie dodawać nagłówki do każdej odpowiedzi.
To są nagłówki, które dodałem
.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")
To są inne nagłówki, które próbowałem i które zawiodły
.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")
Dzięki tej metodzie nagłówki Cross Site są poprawnie stosowane i pojawiają się w mojej konsoli programisty oraz w Postmanie. Problem jednak polega na tym, że gdy przeglądarka przechodzi Access-Control-Allow-Origin
pomyślnie, przeglądarka internetowa sycze pasuje (sądzę), Access-Control-Allow-Headers
stwierdzając415 (Unsupported Media Type)
Więc metoda brutalnej siły też nie działa
Wreszcie
Czy ktoś doszedł do tego i mógł pomóc, czy po prostu wskazać mi właściwy kierunek?
EDYTOWAĆ
Aby uzyskać wywołania API, musiałem przestać używać JQuery i przejść na XMLHttpRequest
format czystego Javascript .
Próba 1
Udało mi się dostać Microsoft.AspNetCore.Cors
do pracy, postępując zgodnie z odpowiedzią MindingData, z wyjątkiem Configure
metody wstawiania app.UseCors
wcześniej app.UseMvc
.
Ponadto po zmieszaniu z JavaScript API Solution options.AllowAnyOrigin()
do obsługi symboli wieloznacznych zaczęło działać.
Próba 2
Udało mi się więc sprawić, że próba 2 (brutalne zmuszanie) do działania ... z jedynym wyjątkiem, że Wildcard dla Access-Control-Allow-Origin
nie działa i jako taki muszę ręcznie ustawić domeny, które mają do niego dostęp.
Oczywiście nie jest idealny, ponieważ chcę, aby ten interfejs WebAPI był szeroko otwarty dla wszystkich, ale przynajmniej działa dla mnie na osobnej stronie, co oznacza, że to początek
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)
problemu ustawContent-Type
nagłówek żądania naapplication/json
.