.NET Core UseCors() не добавляет заголовки
Это будет дубликатом Как работает заголовок Access-Control-Allow-Origin?, но метод там также не работает для меня. Я надеюсь, что просто что-то упустил.
Я пытаюсь получить Access-Control-Allow-Origin
заголовок в моем ответе от моего.NET Core Web API, к которому я обращаюсь через AJAX.
Я пробовал несколько вещей. Все, если не указано иное, были в Startup.cs
файл.
Способ 1
Согласно документации Microsoft:
public void ConfigureServices(IServiceCollection services)
{
// Add database
services.AddDbContext<DbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DbConnection")));
// Add the ability to use the API with JSON
services.AddCors();
// Add framework services.
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
serviceScope.ServiceProvider.GetService<DbContext>().Database.Migrate();
serviceScope.ServiceProvider.GetService<DbContext>().EnsureSeedData();
}
}
app.UseCors(builder => builder.WithOrigins("https://localhost:44306").AllowAnyMethod());
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
Authority = Configuration["Authentication:AzureAd:AADInstance"] + Configuration["Authentication:AzureAd:TenantId"],
Audience = Configuration["Authentication:AzureAd:Audience"],
});
app.UseMvc();
}
Способ 2
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddCors(options => options.AddPolicy("AllowWebApp",
builder => builder.AllowAnyMethod()
.AllowAnyMethod()
.AllowAnyOrigin()));
//.WithOrigins("https://localhost:44306")));
// ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// ...
app.UseCors("AllowWebApp");
// ...
}
Я также попытался добавить [EnableCors("AllowWebApp")]
на контроллере и методе.
От Почтальона я получаю:
кодирование содержимого → gzip
тип контента → текст / обычный текст; кодировка = UTF-8
дата → ср, 25 янв 2017 04:51:48 GMT
сервер → пустельга
статус → 200
варьировать → Принять кодировку
x-powered-by → ASP.NET
x-sourcefiles → =? UTF-8? B? [УДАЛЕНО]
Я также попробовал это в Chrome и получил похожие заголовки.
Если это имеет значение, метод, к которому я пытаюсь получить доступ, имеет Authorize
атрибут на это. Но эта часть должна работать нормально (по крайней мере, я получаю хороший ответ)
Итак, я что-то упускаю очень очевидное, или это сломалось? В настоящее время я использую версию 1.1.0.
Отредактируйте добавление JS и заглушки контроллера
function getContactPreviews(resultsCallback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = () => {
if (xmlhttp.readyState == XMLHttpRequest.DONE && xmlhttp.status == 200) {
resultsCallback(JSON.parse(xmlhttp.response));
}
}
xmlhttp.open("GET", "https://localhost:44357/api/User/ContactsPreview", true);
xmlhttp.setRequestHeader("Authorization", "Bearer " + localStorage.getItem("AuthorizationToken"));
xmlhttp.send();
}
Заглушка контроллера
[Authorize]
[Route("api/[controller]")]
public class UserController : ApiController
{
[HttpGet(nameof(ContactsPreview))]
[EnableCors("AllowWebApp")]
public IEnumerable<Customer> ContactsPreview()
{
// ...
}
}
8 ответов
Проблема заключается в том, что при использовании аутентификации Bearer (или любой другой, которую я себе представляю), он добавляет заголовок "Авторизация", и сервер выдаст одобрение только в том случае, если настройка разрешает этот заголовок.
Есть два способа решения проблемы, и ниже приведен единственный необходимый код. Это идет в Configure()
метод в Startup.cs
в решении веб-API.
Способ 1: разрешить все заголовки
app.UseCors(builder => builder.WithOrigins("https://localhost:44306")
.AllowAnyMethod()
.AllowAnyHeader());
Способ 2: разрешить определенные заголовки
app.UseCors(builder => builder.WithOrigins("https://localhost:44306")
.AllowAnyMethod()
.WithHeaders("authorization", "accept", "content-type", "origin"));
Дополнительные заголовки, потому что, согласно документации:
Браузеры не совсем согласуются с тем, как они устанавливают Access-Control-Request-Headers. Если вы установили заголовки на что-либо, кроме "*", вы должны включить как минимум "accept", "content-type" и "origin" плюс любые пользовательские заголовки, которые вы хотите поддерживать.
Заголовок Access-Control-Allow-Origin возвращается, только если:
- Запрос включает заголовок "Origin".
- Запрашиваемый источник соответствует политике CORS.
Затем сервер возвращает ACAO-заголовок с URL-адресом источника в качестве значения.
Заголовок Origin обычно устанавливается объектом XMLHttpRequest.
Для получения дополнительной информации см. Как работает CORS
В
Startup.cs
в конце
ConfigureServices()
Добавь это:
services.AddCors();
Затем в
Configure()
вверху добавьте это:
app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().WithExposedHeaders("*"));
// alternatively you could use .With... methods to specify your restrictions:
// app.UseCors(x => x.WithOrigins("http://domain1.com").WithMethods("GET","POST").WithHeaders("Authorization").WithExposedHeaders("*"));
Сегодня я потратил часы на эту проблему только для того, чтобы обнаружить это, потому что .Net Core 3 не поддерживает предварительные запросы OPTIONS, если вы используете метод маршрутизации конечных точек RequirePolicy для включения CORS!
В официальной документации это упоминается, но это не было вызвано явным предупреждением, поэтому я полностью его пропустил.
Следующее устранит проблему, но применит глобальную политику CORS, поэтому будьте осторожны, покупатель!
Конфигурация услуги:
public void ConfigureServices(IServiceCollection services)
{
string[] corsOrigins = Configuration.GetSection("AllowedHosts").Get<string[]>();
services.AddCors(options =>
{
options.AddPolicy("AllowConfiguredOrigins", builder => builder
.WithOrigins(corsOrigins)
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
);
});
...
В принципе, не делайте этого:
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireCors("AllowConfiguredOrigins");
});
...
... сделай это вместо этого
Настроить ()
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseCors("AllowConfiguredOrigins");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
...
По состоянию на 17.03.2009..NET Core версии 2.1:
Это, возможно, сэкономит некоторое время другим бедным людям... В какой-то момент я начал разочаровываться и чуть не разочаровался в.NET Core WebApi как отдельном проекте.
В реальных условиях в функциях запуска есть другие конфигурации, например, у меня были Swagger, DI-регистрации и т. Д. Я не мог заставить работать кровавую вещь, пока я не поставил методы AddCors() и UseCors() в качестве первого вызываемого метода. в настройках функций.
// 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("SomePolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors("SomePolicy");
После этого вызовы из приложения Angular 6 (клиентские вызовы Swagger Typescript) начали работать как очарование.
В файле Startup.cs добавьте следующее
public CorsPolicy GenerateCorsPolicy(){
var corsBuilder = new CorsPolicyBuilder();
corsBuilder.AllowAnyHeader();
corsBuilder.AllowAnyMethod();
corsBuilder.AllowAnyOrigin(); // For anyone access.
//corsBuilder.WithOrigins("http://localhost:56573"); // for a specific url. Don't add a forward slash on the end!
corsBuilder.AllowCredentials();
return corsBuilder.Build();
}
В методе ConfigureServices:
services.AddCors(options =>
{
options.AddPolicy("AllowAllOrigins", GenerateCorsPolicy());
});
// Применять CORS глобально в приложении // В метод Configure добавить
app.UseCors("AllowAllOrigins");
[DisableCors]
Используя атрибут DisableCors, мы можем отключить CORS для контроллера или действия.
// Включение базы контроллера CORS - если вы применяете глобально, вам это не нужно.
[EnableCors("AllowAllOrigins")]
public class HomeController: Controller {}
Я хочу добавить еще одну возможность для тех, кто, возможно, последовал приведенному выше совету, но он все еще не работает. В моем случае я не получал возвращаемый заголовок (или получал его только по первому запросу) из-за порядка регистрации в конвейере.
Я изменил порядок с этого:
app.UseResponseCaching();
app.UseHttpsRedirection();
app.UseCors("WideOpen");
app.UseMvc();
К этому:
app.UseCors("WideOpen");
app.UseResponseCaching();
app.UseHttpsRedirection();
app.UseMvc();
Это решило мою проблему.
services.AddCors(options => options.AddDefaultPolicy(
builder => builder
.SetIsOriginAllowed((x => true))
.AllowAnyHeader()
.AllowAnyMethod()));