Не удается включить CORS в веб-интерфейсе ASP.Net Core. - PullRequest
0 голосов
/ 06 сентября 2018

Я создал проект веб-API ASP.Net CORE с одним контроллером и теперь хотел бы вызвать его из клиентского (React) веб-приложения.

Однако вызов завершается неудачно, так как в запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». "

При вызове той же конечной точки из Fiddler ожидаемые заголовки ответа отсутствуют.

Благодаря ATerry у меня появилось еще одно понимание: заголовки отсутствуют, поскольку веб-приложение React и веб-API .Net Core размещены в одном блоке. React заполняет запрос Origin: заголовок, который совпадает с полем (API), таким образом, сервер (действительно умный в этом вопросе) не добавляет заголовки ответа Allow -... Однако приложение React отклоняет ответ из-за отсутствия этих заголовков.

Я использую .Net Core v2.1 (последняя на момент написания статьи).

Я построил код на основе

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

Я проверил это

https://weblog.west -wind.com / сообщений / 2016 / Сентябрь / 26 / ASPNET-Core-и-CORS-Gotchas

CORS в .NET Core

Как включить CORS в ASP.NET Core

... но ни одно из предложений не сработало.

Есть идеи?

Вот как я настраиваю приложение .Net Core (код изменен с фактического, чтобы попытаться разрешить что-либо):

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Enable CORS (Cross Origin Requests) so that the React app on a different URL can access it
        // See https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1
        services.AddCors(options =>
        {
            options.AddPolicy(Global.CORS_ALLOW_ALL_POLICY_NAME, builder => builder
                .AllowAnyOrigin()
                .AllowAnyHeader()
                .AllowAnyMethod()
                .AllowCredentials());
        });

        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseCors(Global.CORS_ALLOW_ALL_POLICY_NAME);

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

Не справившись с вышеперечисленным, я добавил атрибуты CORS в класс контроллера и методы контроллера:

[Route("api/[controller]")]
[ApiController]
[EnableCors(Global.CORS_ALLOW_ALL_POLICY_NAME)]
public class DealsController : ControllerBase
{
[...]
[HttpGet]
    [EnableCors(Global.CORS_ALLOW_ALL_POLICY_NAME)]
    public ActionResult<List<Deal>> GetAll()
    {
        return Store;
    }
}

Заголовки ответа, которые я получаю:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Kestrel
X-Powered-By: ASP.NET
Date: Thu, 06 Sep 2018 12:23:27 GMT

Отсутствуют заголовки:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000

Ответы [ 4 ]

0 голосов
/ 30 января 2019

Недавно я застрял с этой же проблемой, но сомневался, что моя связана с CORS. Поэтому я решил развернуть приложение в своем локальном IIS, чтобы проверить, будет ли оно решено каким-либо образом. Затем проверил журналы и обнаружил проблему, относящуюся к циклической ссылке в моделях данных - «Обнаружен цикл самоссылки для свойства ...». Применил действие в Startup.js для решения проблемы следующим образом:

    services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
                .AddJsonOptions(options =>
                {
                    options.SerializerSettings.Formatting = Formatting.Indented;

                    // this line
                    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
                });
0 голосов
/ 27 сентября 2018

Полагаю, что он должен работать и с хостингом LOCALHOST, просто внесите следующие изменения и удалите все дополнительные изменения / конфигурации.

Заменить это:

        // Enable CORS (Cross Origin Requests) so that the React app on a different URL can access it
    // See https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1
    services.AddCors(options =>
    {
        options.AddPolicy(Global.CORS_ALLOW_ALL_POLICY_NAME, builder => builder
            .AllowAnyOrigin()
            .AllowAnyHeader()
            .AllowAnyMethod()
            .AllowCredentials());
    });

с этим:

services.AddCors();

и замените это:

app.UseCors(Global.CORS_ALLOW_ALL_POLICY_NAME);

с этим:

app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

Примечание:

  • Даже если ваше приложение Web Api и React настроено на LOCALHOST, это не значит, что они принадлежат к одному источнику, это потому, что они размещены на другом порту, как приложение реакции на LOCALHOST: 3000 и Web Api Размещено на LOCALHOST: 5000. Web api будет жаловаться, если клиент (реагирует на приложение) запрашивает другой порт.

  • Над кодом Web Api разрешено ЛЮБОЕ ПРОИСХОЖДЕНИЕ, а в производственных приложениях это небезопасно, поэтому вам необходимо разрешить доступ к ORIGIN для CORS.

0 голосов
/ 10 января 2019

Вы можете попробовать что-то вроде ниже, как объяснено здесь: https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.2

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

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
    ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    // Shows UseCors with named policy.
    app.UseCors("AllowSpecificOrigin");

    app.Run(async (context) =>
    {
        await context.Response.WriteAsync("Hello World!");
    });
}

В вашем сценарии его можно заменить на что-то вроде кода ниже.

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {

        services.AddCors(options => options.AddPolicy(Global.CORS_ALLOW_ALL_POLICY_NAME,
                builder =>
                {
                    builder.AllowAnyOrigin()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                }));

        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseCors(Global.CORS_ALLOW_ALL_POLICY_NAME);

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

Этот код может не отличаться от вашего, однако есть небольшая разница в том, как определяются действия (то, что вы называете строителем). Я надеюсь, что это помогает, удачи! :)

0 голосов
/ 11 сентября 2018

Решил проблему путем изменения URL-адреса, используемого для доступа к серверу, с адреса на основе localhost на IP-адрес (localhost / api на 192.168.1.96/api).

Кажется, что часть упомянутой ATerry фильтрации основана на имени хоста: IIS не отправляет заголовки Allow -..., если hostname - localhost. Беда в том, что Реакт требует их.

...