Включить заголовок 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 на одной конечной точке