Що я намагаюся зробити
У мене є резервний веб-API ASP.Net Core, розміщений на Azure Free Plan (вихідний код: https://github.com/killerrin/Portfolio-Backend ).
Також у мене є веб-сайт клієнта, який я хочу використати для цього API. Клієнтська програма не розміщуватиметься на Azure, а навпаки, розміщуватиметься на Сторінках Github або на іншій службі веб-хостингу, до якої я маю доступ. Через це доменні імена не вирівняються.
З огляду на це, мені потрібно включити CORS на стороні Web API, однак я вже кілька годин намагався майже все, і він відмовляється працювати.
Як у мене встановлена програма клієнта Це просто простий клієнт, написаний на React.js. Я дзвоню API через AJAX в Jquery. Сайт React працює, тому я знаю, що це не так. Виклик API Jquery працює, як я підтвердив у Спробі 1. Ось як я здійснюю дзвінки
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);
}
}
});
Що я спробував
Спроба 1 - "правильний" спосіб
https://docs.microsoft.com/en-us/aspnet/core/security/cors
Я дотримувався цього підручника на веб-сайті Майкрософт до T, пробуючи всі три варіанти включення його в глобальному масштабі в Startup.cs, налаштування його на кожен контролер і спробування його на кожній дії.
Дотримуючись цього методу, Cross Domain працює, але лише на одній дії на одному контролері (POST to AccountController). По всьому іншому, Microsoft.AspNetCore.Cors
середнє програмне забезпечення відмовляється встановлювати заголовки.
Я встановив Microsoft.AspNetCore.Cors
через NUGET і версія є1.1.2
Ось як у мене це налаштування в 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();
...
...
...
}
Як бачите, я все роблю так, як сказано. Я додаю Cors перед MVC обидва рази, і коли це не спрацьовувало, я намагався надіти [EnableCors("MyPolicy")]
кожен контролер так
[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class AdminController : Controller
Спроба 2 - жорстоке примушування
https://andrewlock.net/adding-default-security-headers-in-asp-net-core/
Після декількох годин спроб попередньої спроби, я зрозумів, що спробую це перешкодити, намагаючись встановити заголовки вручну, змушуючи їх працювати на кожну відповідь. Я зробив це, виходячи з цього підручника про те, як вручну додати заголовки до кожної відповіді.
Це заголовки, які я додав
.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")
Це інші заголовки, які я спробував, які не вдалося
.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")
За допомогою цього методу правильно застосовуються заголовки крос-сайтів, і вони відображаються в моїй консолі розробника та в "Поштові". Проблема, однак, полягає в тому, що під час проходження Access-Control-Allow-Origin
перевірки, веб-браузер накидає шипучу форму (я вважаю), Access-Control-Allow-Headers
заявляючи415 (Unsupported Media Type)
Тож метод грубої сили також не працює
Нарешті
Хтось змусив це працювати і міг би подати руку, чи просто міг би вказати мені в правильному напрямку?
EDIT
Тож, щоб отримати виклики API, мені довелося перестати використовувати JQuery і перейти до XMLHttpRequest
формату чистого Javascript .
Спроба 1
Мені вдалося Microsoft.AspNetCore.Cors
приступити до роботи, дотримуючись відповіді MindingData, за винятком Configure
методу, що ставив app.UseCors
раніше app.UseMvc
.
Крім того, при змішуванні з Javascript API Рішенням options.AllowAnyOrigin()
для підтримки підстановки почали працювати також.
Спроба 2
Тож мені вдалося змусити Attempt 2 (грубо змусити його) працювати ... за єдиним винятком, що Wildcard для Access-Control-Allow-Origin
не працює, і мені в такому випадку доводиться вручну встановлювати домени, які мають доступ до нього.
Це, очевидно, не ідеально, оскільки я просто хочу, щоб цей WebAPI був широко відкритий для всіх, але він принаймні працює для мене на окремому сайті, це означає, що це початок
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)
проблеми встановітьContent-Type
заголовок запиту наapplication/json
.