Включить заголовок OPTIONS для CORS на .NET Core Web API

Я решил эту проблему после того, как не нашел решение на Stackoverflow, поэтому я делюсь своей проблемой здесь и решением в ответе.

После включения политики кросс-домена в моем приложении .NET Core Web Api с помощью AddCors она по-прежнему не работает в браузерах. Это связано с тем, что браузеры, включая Chrome и Firefox, сначала отправят запрос OPTIONS, и мое приложение просто ответит с помощью 204 No Content.

Ответ 1

Добавьте класс связующего программного обеспечения в ваш проект для обработки глагола OPTIONS.

using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Hosting;

namespace Web.Middlewares
{
    public class OptionsMiddleware
    {
        private readonly RequestDelegate _next;

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

        public Task Invoke(HttpContext context)
        {
            return BeginInvoke(context);
        }

        private Task BeginInvoke(HttpContext context)
        {
            if (context.Request.Method == "OPTIONS")
            {
                context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)context.Request.Headers["Origin"] });
                context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
                context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });
                context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
                context.Response.StatusCode = 200;
                return context.Response.WriteAsync("OK");
            }

            return _next.Invoke(context);
        }
    }

    public static class OptionsMiddlewareExtensions
    {
        public static IApplicationBuilder UseOptions(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<OptionsMiddleware>();
        }
    }
}

Затем добавьте app.UseOptions(); это как первая строка в Startup.cs в методе Configure.

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

Ответ 2

Я знаю, что ответили. Просто отвечаю с обновленной информацией. Так что это поможет другим.

Теперь он встроен в каркас ASP.NET Core.

Просто следуйте https://docs.microsoft.com/en-us/aspnet/core/security/cors

и заменить

    app.UseCors(builder =>
   builder.WithOrigins("http://example.com"));

с

        app.UseCors(builder =>
       builder.WithOrigins("http://example.com")
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials());

Ответ 3

Это сработало для меня:

Убедитесь, что это:

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

Происходит до любого из них:

app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseCookiePolicy();

Помните, мы имеем дело с "конвейером". Материал Cors должен быть первым.

-gimzani

Ответ 4

Нет необходимости в дополнительном промежуточном программном обеспечении. Как уже упоминалось выше, единственное, что нужно, это метод OPTIONS, разрешенный в конфигурации Cors. Вы можете использовать AllowAnyMethod, как указано здесь: fooobar.com/questions/1669559/...

Но безопаснее просто разрешить такие вещи, как это:

app.UseCors(builder => builder
.WithOrigins("https://localhost", "https://production.company.com") /* list of environments that will access this api */
.WithMethods("GET", "OPTIONS") /* assuming your endpoint only supports GET */
.WithHeaders("Origin", "Authorization") /* headers apart of safe-list ones that you use */
);

Некоторые заголовки всегда разрешены:https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_request_header

Ответ 5

Я хотел разрешить это для одного метода, не используя промежуточное программное обеспечение, чтобы разрешить это на любом методе. Вот что я закончил делать:

Ручная обработка метода "ОПЦИИ"

[HttpOptions("/find")]
public IActionResult FindOptions()
{
    Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)Request.Headers["Origin"] });
    Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
    Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST, OPTIONS" }); // new[] { "GET, POST, PUT, DELETE, OPTIONS" }
    Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
    return NoContent();
}

[HttpPost("/find")]
public async Task<IActionResult> FindOptions([FromForm]Find_POSTModel model)
{
    AllowCrossOrigin();

    // your code...
}

private void AllowCrossOrigin()
{
    Uri origin = null;
    Uri.TryCreate(Request.Headers["Origin"].FirstOrDefault(), UriKind.Absolute, out origin);

    if (origin != null && IsOriginAllowed(origin))
        Response.Headers.Add("Access-Control-Allow-Origin", $"{origin.Scheme}://{origin.Host}");
}

И, конечно, вы можете реализовать IsOriginAllowed как вы хотите

private bool IsOriginAllowed(Uri origin)
{
    const string myDomain = "mydomain.com";
    const string[] allowedDomains = new []{ "example.com", "sub.example.com" };

    return 
           allowedDomains.Contains(origin.Host) 
           || origin.Host.EndsWith($".{myDomain}");
}

Вы можете найти более подробную информацию о том, как включить CORS для запросов POST на одной конечной точке