Як увімкнути CORS в ASP.net Core WebAPI


189

Що я намагаюся зробити

У мене є резервний веб-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"));

2
Для своєї 415 (Unsupported Media Type)проблеми встановіть Content-Typeзаголовок запиту на application/json.
Технецій

5
Дякуємо, що витратили час на написання такого описового питання.
користувач1007074

1
Якщо ви тестуєте за допомогою Postman, переконайтеся, що ви встановили Origin на * або щось для заголовка запиту, тоді спроба №1 повинна працювати. Без цього заголовка Access-Control-Allow-Origin не буде повернуто у заголовку відповіді.
tala9999

Відповіді:


238

Оскільки у вас є дуже проста політика CORS (Дозволити всі запити з домену XXX), не потрібно робити це настільки складним. Спробуйте виконати наступне (Дуже основна реалізація CORS).

Якщо ви ще цього не зробили, встановіть пакунок нульових CORS.

Install-Package Microsoft.AspNetCore.Cors

У методі ConfigureServices вашого startup.cs додайте служби CORS.

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(); // Make sure you call this previous to AddMvc
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

Потім у свій метод Налаштування свого startup.cs додавайте наступне:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // Make sure you call this before calling app.UseMvc()
    app.UseCors(
        options => options.WithOrigins("http://example.com").AllowAnyMethod()
    );

    app.UseMvc();
}

Тепер дайте йому піти. Політика полягає в тому, коли потрібно різну політику для різних дій (наприклад, різні хости або різні заголовки). Для вашого простого прикладу вам це справді не потрібно. Почніть з цього простого прикладу і налаштуйте, як вам потрібно, звідти.

Подальше читання: http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/


3
XMLHttpRequest не може завантажити andrewgodfroyportfolioapi.azurewebsites.net/api/Authentication . Відповідь на запит перед польотом не проходить перевірку контролю доступу: у запитуваному ресурсі немає заголовка "Access-Control-Allow-Origin". Походження " localhost: 3000 " не має права доступу. Відповідь мала код статусу HTTP 415.
вбивця

7
Це навряд чи вийде, коли ви реєструєтесь app.UseCors ПІСЛЯ `` app.UseMvc () `. Посередницькі вироби виконуються в порядку, в якому вони зареєстровані
Tseng

24
використовуючи app.UseCors перед app.UseMvc, у методі Налаштування, здається, працює. Чомусь послідовність дійсно має значення.
MrClan

1
Для мене найбільша проблема CORS в 2.0 полягає в тому, що він не говорить про те, що не так, просто мовчки не в змозі встановити заголовки CORS. Примітка . Не забудьте додати всі необхідні заголовки до політики, інакше вона не вийде (у мене був тип вмісту). Також дивно для мене, що проміжне програмне забезпечення CORS не гальмує обробку запитів, просто повідомляє в журналах, що походження заборонено, і .. Проходить подальший запит (порядок середнього програмного забезпечення був правильним).
Андрій M4n0w4R

2
Мені довелося ввімкнути options.DisableHttpsRequirement();для того, щоб будь-що з цього спрацювало. Здається, параметри https cors не застосовуються.
Майкл Браун

208
  • У програму ConfigureServices додати services.AddCors(); ДО ПЕРЕД служб.AddMvc ();

  • Додати UseCors у налаштуваннях

     app.UseCors(builder => builder
         .AllowAnyOrigin()
         .AllowAnyMethod()
         .AllowAnyHeader());   
     app.UseMvc();

Основний момент - це те, що додати app.UseCors, раніше app.UseMvc().

Переконайтеся, що ви оголосили функцію CORS перед MVC, щоб проміжне програмне забезпечення запускалося до того, як конвеєр MVC отримає контроль та припинить запит.

Після роботи вищевказаного методу ви можете змінити його, щоб налаштувати конкретний ORIGIN, щоб приймати дзвінки api та уникати залишати API так відкритим для будь-кого

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
    {
        builder.WithOrigins("http://localhost:4200").AllowAnyMethod().AllowAnyHeader();
    }));

    services.AddMvc();
}

У методі налаштування скажіть CORS використовувати створену вами політику:

app.UseCors("ApiCorsPolicy");
app.UseMvc();

Я щойно знайшов цю компактну статтю на цю тему - https://dzone.com/articles/cors-in-net-core-net-core-security-part-vi


1
Це працює для мене. codeproject.com/Articles/1150023/…
hubert17

17
Це дійсно повинно отримати більше результатів як хороший "вихідний" пункт. З мого досвіду за 25 років кодування завжди приємно знати, як відкрити шлюзи, щоб переконатися, що вони насправді "працюють", а потім закривати / захищати речі за потребою.
Інді-Джонс

4
Тільки кажучи про це, на відміну Configure()від замовлення тут не дуже важливоConfigureServices()
B12Toaster

Я використовував посилання в «Далі читання», і ці кроки вирішили цю помилку. Я не був впевнений, де слід розмістити ці зміни (я думав, що API). Посилання підтвердило, що їх слід розмістити в API. Дякую за допомогу. Я цілком крутив колеса з цією помилкою.
Річард

1
FYI - У специфікації CORS також зазначено, що встановлення джерел на "*" (усі джерела) є недійсним, якщо є заголовок Access-Control-Allow-Credentials. Значення ви не можете використовувати AllowCredentials()з , AllowAnyOrigin()як і вище. Для використання AllowCredentials()потрібно встановити WithOrigins(). docs.microsoft.com/en-us/aspnet/core/security/…
Nick De Beer

28

Я створив власний клас середнього програмного забезпечення, який працював на мене, я думаю, що з класом середнього програмного забезпечення .net core щось не так

public class CorsMiddleware
{
    private readonly RequestDelegate _next;

    public CorsMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public Task Invoke(HttpContext httpContext)
    {
        httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
        httpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
        httpContext.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
        httpContext.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
        return _next(httpContext);
    }
}

// Extension method used to add the middleware to the HTTP request pipeline.
public static class CorsMiddlewareExtensions
{
    public static IApplicationBuilder UseCorsMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<CorsMiddleware>();
    }
}

і використовував його таким чином у startup.cs

app.UseCorsMiddleware();

Дуже елегантний спосіб роботи Access-Control-Allow-Origin.
Artur Poniedziałek

Це працює на WebAPI та MVC і не має залежностей, Дякую!
Джо

Я теж скептично ставився до цього, але це працювало на мене. Я намагався в основному будь-яким іншим методом досягти цього, що міг знайти в Інтернеті, але незалежно від того, що сервер не відповів би заголовками доступу. Це спрацювало чудово. Я працюю aspnetcore 2.1.
Йордан

Ви повинні повернути заголовки cors, лише якщо клієнт надсилає заголовок "Origin" у запиті. У оригіналі CospMiddleware це виглядає приблизно так:if (!context.Request.Headers.ContainsKey(CorsConstants.Origin)) return this._next(context);
Андрій Пригоршнєв,

1
Можливо, "щось не так з класом середнього програмного забезпечення .net core", оскільки ви просто не додаєте заголовок "Origin" під час тестування його на curl або щось подібне. Браузери додають цей заголовок автоматично, коли ви робите запит у js-коді.
Андрій Пригоршньов

18

У моєму випадку лише getзапит працює добре відповідно до відповіді MindingData. Для інших типів запиту потрібно написати:

app.UseCors(corsPolicyBuilder =>
   corsPolicyBuilder.WithOrigins("http://localhost:3000")
  .AllowAnyMethod()
  .AllowAnyHeader()
);

Не забудьте додати .AllowAnyHeader()


Погодьтеся з Towhid, що AllowAnyHeader () потрібен. Він дозволяє серверу отримувати запит OPTIONS, якщо в запиті HEADER щось не вистачає.
Рівон

.AllowAnyHeader () зробив це для мене, у мене виникли проблеми з попередньою реакцією на політ.
takaz

11

Для того, щоб розширити свою присутність на user8266077 «и відповіді , я виявив , що все ще потрібна відповідь OPTIONS харчування для предполітних запитів в .NET 2.1 ядро-превью для мого випадку використання:

// https://stackoverflow.com/a/45844400
public class CorsMiddleware
{
  private readonly RequestDelegate _next;

  public CorsMiddleware(RequestDelegate next)
  {
    _next = next;
  }

  public async Task Invoke(HttpContext context)
  {
    context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
    context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
    // Added "Accept-Encoding" to this list
    context.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Accept-Encoding, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
    context.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
    // New Code Starts here
    if (context.Request.Method == "OPTIONS")
    {
      context.Response.StatusCode = (int)HttpStatusCode.OK;
      await context.Response.WriteAsync(string.Empty);
    }
    // New Code Ends here

    await _next(context);
  }
}

а потім увімкнув посередництво на зразок так у Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  app.UseMiddleware(typeof(CorsMiddleware));
  // ... other middleware inclusion such as ErrorHandling, Caching, etc
  app.UseMvc();
}

1
Рекомендую додати таким чином програмне забезпечення:app.Use<CorsMiddleware>();
Albert221

Ви можете замінити ці 2 ligne: context.Response.StatusCode = (int) HttpStatusCode.OK; очікувати контексту.Response.WriteAsync (string.Empty); з простим: повернення;
Хайха

1
Щоб розширити розширення відповіді @ user8266077: Остерігайтеся, що якщо запит з якоїсь іншої причини не вдасться, це проміжне програмне забезпечення видасть виняток, і заголовки не будуть встановлені. Це означає, що у фронтенді він все ще буде виглядати як проблема CORS, хоча це щось зовсім інше. Я обійшов це, вловивши будь-які винятки await _next(context)та встановивши код статусу та відповідь вручну, якщо це трапиться. Я також повинен був додати "авторизацію" до Access-Control-Allow-Headers для попереднього запиту на політ для роботи під час отримання запитів з реакції, яка вимагає авторизації.
Адам

11
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {      
       app.UseCors(builder => builder
                .AllowAnyHeader()
                .AllowAnyMethod()
                .SetIsOriginAllowed((host) => true)
                .AllowCredentials()
            );
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors();
    }

.SetIsOriginAllowed ((host) => true) вирішив це для мене.
JensB

уау, тому я повністю очікував, що будь-яка інша відповідь буде працювати перед цим маленьким лише 3 голосами. але я ретельно спробував кожного, ... на примху я пішов за вашим, і це спрацювало. дякую
roberto tomás

Це той, який працював для мене на .NET Core 3.1, щоб дозволити майже все.
JustinHui

10

Я боровся з цим протягом ДЕНЬ.

Я , нарешті , отримав його на роботу, рухаючись app.UseCors(CORS_POLICY);в ТОП з Configure().

https://weblog.west-wind.com/posts/2016/sep/26/aspnet-core-and-cors-gotchas

Переконайтеся, що ви оголосили функцію CORS раніше> MVC, оскільки заголовки повинні бути застосовані до завершення запиту MVC.

<= Незважаючи на те, що мій додаток не дзвонив UseMVC(), перехід UseCors()до вершини вирішив проблему

Також:

  • Microsoft.AspNetCore.Corsвикористовувався як необхідний пакет NuGet в .Net Core 2 і новіших версіях; Тепер він автоматично є частиною Microsoft.AspNetCore в. Net Core 3 і новіших версіях.
  • builder.AllowAnyOrigin() і .AllowCredentials() варіанти CORS тепер взаємовиключними .Net Core 3 і вище
  • Політика CORS, схоже, вимагає кутового виклику сервера https. Здавалося, що URL-адреса http видає помилку CORS незалежно від конфігурації CORS-сервера .Net Core. Наприклад, http://localhost:52774/api/Contactsдав би помилку CORS; просто змінивши URL-адресу на https://localhost:44333/api/Contactsпрацюючу.

Додаткова примітка :

У моєму випадку CORS не працюватиме, поки я не рухаюся app.UseCors()вище app.UseEndpoints(endpoints => endpoints.MapControllers()).


2
Цей варіант повинен відповісти, якщо ви використовуєте Net Core 3. Дякую, що врятували мені життя!
Канада Ван

2
"При маршрутизації кінцевих точок проміжне програмне забезпечення CORS повинно бути налаштоване для виконання між викликами UseRouting та UseEndpoints. Неправильна конфігурація призведе до того, що середнє програмне забезпечення перестане функціонувати належним чином." тут docs.microsoft.com/en-us/aspnet/core/security/…
Марк

"При маршрутизації кінцевих точок проміжне програмне забезпечення CORS повинно бути налаштоване для виконання між викликами UseRouting та UseEndpoints. Неправильна конфігурація призведе до того, що середнє програмне забезпечення перестане функціонувати належним чином." тут docs.microsoft.com/en-us/aspnet/core/security/…
Марк

7

Жодна з перерахованих вище процедур не допомогла, і тоді я прочитав статтю, яка вирішила проблему.

Нижче наведено код.

public void ConfigureServices(IServiceCollection services)
{
    // Add service and create Policy with options
    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder => builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials() );
    });


    services.AddMvc(); 
}

і

public void Configure(IApplicationBuilder app)
{
    // ...

    // global policy - assign here or on each controller
    app.UseCors("CorsPolicy");

і на вершині мого методу дій

[EnableCors("CorsPolicy")]

2
Це, мабуть, погана ідея: не слід змішувати проміжне програмне забезпечення ( app.UseCors()) [EnableCors()]в одному додатку. Ви повинні використовувати те чи інше, але не обидва: docs.microsoft.com/en-us/aspnet/core/security/… :Use the [EnableCors] attribute or middleware, not both in the same app.
FoggyDay

4

спробуйте додати jQuery.support.cors = true;до виклику Ajax

Можливо, дані, які ви надсилаєте в API, хитрі,

спробуйте додати наступну функцію JSON

        var JSON = JSON || {};

    // implement JSON.stringify serialization
    JSON.stringify = JSON.stringify || function (obj) {

        var t = typeof (obj);
        if (t != "object" || obj === null) {

            // simple data type
            if (t == "string") obj = '"' + obj + '"';
            return String(obj);

        }
        else {

            // recurse array or object
            var n, v, json = [], arr = (obj && obj.constructor == Array);

            for (n in obj) {
                v = obj[n]; t = typeof (v);

                if (t == "string") v = '"' + v + '"';
                else if (t == "object" && v !== null) v = JSON.stringify(v);

                json.push((arr ? "" : '"' + n + '":') + String(v));
            }

            return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
        }
    };

    // implement JSON.parse de-serialization
    JSON.parse = JSON.parse || function (str) {
        if (str === "") str = '""';
        eval("var p=" + str + ";");
        return p;
    };

то у своїх даних: об'єкт змінити на

    data: JSON.stringify({
        username: username,
        password: password
    }),

Спасибі за вашу допомогу. Однозначно використали частину відповіді, щоб з’ясувати рішення, врешті-решт, після поєднання відповідей усіх
убивця

4

Найпростіше рішення - додати

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseCors(options => options.AllowAnyOrigin());

        app.UseHttpsRedirection();
        app.UseMvc();
    }

до Startup.cs.


3

Я думаю, що якщо ви використовуєте власне проміжне програмне забезпечення CORS, вам потрібно переконатися, що це дійсно запит CORS , перевіривши заголовок походження .

 public class CorsMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IMemoryCache _cache;
    private readonly ILogger<CorsMiddleware> _logger;

    public CorsMiddleware(RequestDelegate next, IMemoryCache cache, ILogger<CorsMiddleware> logger)
    {
        _next = next;
        _cache = cache;
        _logger = logger;
    }
    public async Task InvokeAsync(HttpContext context, IAdministrationApi adminApi)
    {
        if (context.Request.Headers.ContainsKey(CorsConstants.Origin) || context.Request.Headers.ContainsKey("origin"))
        {
            if (!context.Request.Headers.TryGetValue(CorsConstants.Origin, out var origin))
            {
                context.Request.Headers.TryGetValue("origin", out origin);
            }

            bool isAllowed;
            // Getting origin from DB to check with one from request and save it in cache 
            var result = _cache.GetOrCreateAsync(origin, async cacheEntry => await adminApi.DoesExistAsync(origin));
            isAllowed = result.Result.Result;

            if (isAllowed)
            {
                context.Response.Headers.Add(CorsConstants.AccessControlAllowOrigin, origin);
                context.Response.Headers.Add(
                    CorsConstants.AccessControlAllowHeaders,
                    $"{HeaderNames.Authorization}, {HeaderNames.ContentType}, {HeaderNames.AcceptLanguage}, {HeaderNames.Accept}");
                context.Response.Headers.Add(CorsConstants.AccessControlAllowMethods, "POST, GET, PUT, PATCH, DELETE, OPTIONS");

                if (context.Request.Method == "OPTIONS")
                {
                    _logger.LogInformation("CORS with origin {Origin} was handled successfully", origin);
                    context.Response.StatusCode = (int)HttpStatusCode.NoContent;
                    return;
                }

                await _next(context);
            }
            else
            {
                if (context.Request.Method == "OPTIONS")
                {
                    _logger.LogInformation("Preflight CORS request with origin {Origin} was declined", origin);
                    context.Response.StatusCode = (int)HttpStatusCode.NoContent;
                    return;
                }

                _logger.LogInformation("Simple CORS request with origin {Origin} was declined", origin);
                context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                return;
            }
        }

        await _next(context);
    }

Велике спасибі. Я ледь не збився, запитуючи себе, чому Access-Control-Allow-Originзаголовок не видається сервером. Насправді я надсилав запити поштамтом без Originзаголовка. Це врятувало мені день! (Або принаймні мій переддень;))
Пол Кертчер

2

Виходячи з вашого коментаря у відповіді MindingData, він не має нічого спільного з вашим CORS, він працює чудово.

Ваша дія контролера повертає неправильні дані. HttpCode 415 означає "Непідтримуваний тип медіа". Це відбувається, коли ви передаєте неправильний формат контролеру (тобто XML до контролера, який приймає лише json) або коли ви повертаєте неправильний тип (поверніть Xml у контролер, який оголошується лише для повернення xml).

Надалі слід перевірити наявність [Produces("...")]атрибуту вашої дії


Спасибі за вашу допомогу. Спробував нове рішення, зіграв з відправленням json, і воно спрацювало після того, як я його попрацював і змусив його працювати
killerrin

2

Для мене це не мало нічого спільного з кодом, яким я користувався. Для Azure нам довелося зайти в налаштування Служби додатків, в бічному меню запис "CORS". Там мені довелося додати домен, від якого я просив речі. Колись у мене це було, все було магічним.


2

У запускуSettings.json, під iisSettings, встановіть значення анонімного аутентифікації на істинне:

"iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:4200/",
      "sslPort": 0
    }
  }

Потім у Startup.cs, під ConfigureServices, перед службами.AddMvc, додайте:

services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
{
    builder
        .AllowAnyOrigin()
        .WithHeaders(HeaderNames.AccessControlAllowHeaders, "Content-Type")
        .AllowAnyMethod()
        .AllowCredentials();
}));

а потім у методі настройки перед app.UseMvc () додайте:

app.UseCors("ApiCorsPolicy");

Це зробило це для мене, я спочатку налаштував свій проект на автентифікацію Windows, але потім довелося змінити його на анонімний, я правильно налаштував CORS, але винуватцем цього параметра в launchSettings.json, дякую за те, що ви написали це.
HaRoLD

2

Я використовую. NET CORE 3.1, і я витратив віки, коли я головою об стіну стукав цим, коли зрозумів, що мій код почав працювати, але моє середовище налагодження було порушено, тому ось два підказки, якщо ви намагаєтеся усунути неполадки проблема:

  1. Якщо ви намагаєтесь увімкнути заголовки відповідей за допомогою проміжного програмного забезпечення ASP.NET, заголовок "Access-Control-Allow-Origin" ніколи не з’явиться, навіть якщо він є. Я не знаю, як, але, здається, він додається поза конвеєром (врешті-решт, мені довелося скористатися проводкою, щоб побачити це).

  2. .NET CORE не відправить у відповідь "Access-Control-Allow-Origin", якщо у вашому запиті не буде заголовка "Origin". Листоноша не встановить це автоматично, тому вам потрібно буде додати його самостійно.


2

У моєму випадку я зафіксував UseCors перед UserRouting ..


Я наткнувся на щось подібне, коли я перейшов з dotnet core 2.2 до 3.1. Довелося перемістити app.UseCors () над app.UseRouting (). Ця відповідь вказувала мені в правильному напрямку.
Брендонм

1

.NET Core 3.1

Працював для мене, і як документи говорять про це:

в класі запуску:

readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; 

У методі ConfigureServices ():

    services.AddCors(options =>
    {
        options.AddPolicy(MyAllowSpecificOrigins,
        builder =>
        {
            builder.WithOrigins("http://example.com",
                                "http://www.contoso.com");
        });
    });

У методі Configure ():

    app.UseCors(MyAllowSpecificOrigins);  

https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1


0

Вище я отримав відповідь MindingData, але мені довелося використовувати Microsoft.AspNet.Cors замість Microsoft.AspNetCore.Cors. Я використовую проект .NetCore Web Application API в Visual Studio 2019


2
ПРИМІТКА. Ви не повинні використовувати Microsoft.AspNet.Cors у програмі ASP.Net Cor. Якщо ви перебуваєте на .Net Core 3.0 або новішої версії, вам взагалі не потрібно імпортувати жоден пакет NuGet для CORS. Якщо ви перебуваєте на .Net Core 2.3 або новішої версії, вам потрібна відповідна версія Microsoft.AspNet.Cors від NuGet.
FoggyDay

0

The

Microsoft.AspNetCore.Cors

дозволить вам робити CORS із вбудованими функціями, але він не обробляє запит OPTIONS. Найкращим рішенням поки що є створення нового проміжного програмного забезпечення, як було запропоновано в попередній публікації. Перевірте відповідь, позначену як правильну, у наступному дописі:

Увімкніть заголовок OPTIONS для CORS у .NET Core Web API


0

Простий і легкий спосіб зробити це.

  1. Встановити пакет

Install-Package Microsoft.AspNetCore.Cors

  1. Помістіть цей код нижче у файл startup.cs

app.UseCors(options => options.AllowAnyOrigin());


0

Ось мій код:)

  app.Use((ctx, next) =>
        {
            ctx.Response.Headers.Add("Access-Control-Allow-Origin", ctx.Request.Headers["Origin"]);
            ctx.Response.Headers.Add("Access-Control-Allow-Methods", "*");
            ctx.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            ctx.Response.Headers.Add("Access-Control-Allow-Headers", "AccessToken,Content-Type");
            ctx.Response.Headers.Add("Access-Control-Expose-Headers", "*");
            if (ctx.Request.Method.ToLower() == "options")
            {
                ctx.Response.StatusCode = 204;

                return Task.CompletedTask;
            }
            return next();
        });

0

Ось як я це зробив.

Я бачу, що в деяких відповідях вони встановлюють app.UserCors("xxxPloicy")і ставлять [EnableCors("xxxPloicy")]контролери. Не потрібно робити і те, і інше.

Ось етапи.

У Startup.cs всередині ConfigureServices додайте наступний код.

    services.AddCors(c=>c.AddPolicy("xxxPolicy",builder => {
        builder.AllowAnyOrigin()
        .AllowAnyMethod()
        .AllowAnyHeader();
    }));

Якщо ви хочете застосувати весь проект, то додайте наступний код у методі Налаштування в Startup.cs

app.UseCors("xxxPolicy");

Або

Якщо ви хочете додати його до певних контролерів, тоді додайте код увімкнення корсів, як показано нижче.

[EnableCors("xxxPolicy")]
[Route("api/[controller]")]
[ApiController]
public class TutorialController : ControllerBase {}

Для отримання додаткової інформації: дивіться це


0

Використовуйте спеціальний атрибут дії / контролера, щоб встановити заголовки CORS.

Приклад:

public class AllowMyRequestsAttribute : ControllerAttribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        // check origin
        var origin = context.HttpContext.Request.Headers["origin"].FirstOrDefault();
        if (origin == someValidOrigin)
        {
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", origin);
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Headers", "*");
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Methods", "*");
            // Add whatever CORS Headers you need.
        }
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // empty
    }
}

Потім на контролері / дії веб-API:

[ApiController]
[AllowMyRequests]
public class MyController : ApiController
{
    [HttpGet]
    public ActionResult<string> Get()
    {
        return "Hello World";
    }
}

0

Просто для того, щоб додати відповідь тут, якщо ви використовуєте app.UseHttpsRedirection(), а ви потрапляєте не на порт SSL, подумайте про коментар.


0

Я використовував веб-збірку blazor як клієнт та сервер веб-api asp.net як бекенд, і у мене також виникли проблеми із корсом.

Я знайшов рішення з цим кодом:

Перші рядки моєї основної веб-програми ASP.Net api Startup.cs ConfigureServices та Configure виглядають так:

public void ConfigureServices(IServiceCollection services)
{
   services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
   {
        builder.WithOrigins("http://example.com").AllowAnyMethod().AllowAnyHeader();
    }));

 //other code below...
}

і мій метод Налаштування:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseCors(
        options =>   options.WithOrigins("http://example.com").AllowAnyMethod().AllowAnyHeader()
            );
 //other code below...
}

змінити http://example.comдомен вашого клієнта або IP-адресу


-1
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddJsonOptions(options => {
                    var resolver = options.SerializerSettings.ContractResolver;
                    if (resolver != null)
                        (resolver as DefaultContractResolver).NamingStrategy = null;
                });

            services.AddDbContext<PaymentDetailContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DevConnection"))); //Dependency Injection
            // options => options.UseSqlServer() Lamda Expression

            services.AddCors(options =>
            {
                options.AddPolicy(MyAllowSpecificOrigins,
                    builder =>
                    {
                        builder.WithOrigins("http://localhost:4200").AllowAnyHeader()
                                .AllowAnyMethod(); ;
                    });
            });

Будь ласка, відредагуйте свою відповідь, щоб включити та пояснити свій код та чим він відрізняється від інших відповідей. Це зробить вашу публікацію більш корисною та більш імовірною для її анонсування :)
Das_Geek
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.