.NET Core UseCors()不添加标头

时间:2017-01-25 05:21:11

标签: c# asp.net-core cors asp.net-core-webapi cross-domain-policy

这将是How does Access-Control-Allow-Origin header work?的副本,但那里的方法也不适用于我。我希望我能错过一些东西。

我正在尝试从我的.NET Core Web API获取data.filterNot(_.exists(_.get("field1").contains("def")))标题,我通过AJAX访问它。

我尝试过几件事。除非另有说明,否则所有内容都在Access-Control-Allow-Origin文件中。

方法1

根据Microsoft Documentation

Startup.cs

方法2

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();
}

我还尝试在Controller和Method上添加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"); // ... }

来自邮递员,我得到:

  

content-encoding→gzip
  content-type→text / plain;字符集= UTF-8
  日期→2017年1月25日星期三04:51:48 GMT
  服务器→红隼
  状态→200
  变化→接受编码
  x-powered-by→ASP.NET
  x-sourcefiles→=?UTF-8?B?[删除]

我也在Chrome中试过它,并获得了类似的标题。

如果重要,我尝试访问的方法上有[EnableCors("AllowWebApp")]属性。但那部分应该工作正常(我至少得到了很好的回应)

那么,我是否遗漏了一些非常明显的东西,或者这是否会被打破?我目前正在运行1.1.0版。

编辑添加JS和Controller Stub

Authorize

Controller Stub

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();
}

7 个答案:

答案 0 :(得分:20)

问题在于,当使用Bearer身份验证(或任何我想象的)时,它会添加一个标题“Authorization”,如果设置允许该标头,服务器将只提供一个好的。

有两种方法可以解决问题,下面是所需的唯一代码。它位于Web API解决方案中Configure()的{​​{1}}方法中。

方法1:允许所有标题

Startup.cs

方法2:允许特定标题

app.UseCors(builder => builder.WithOrigins("https://localhost:44306")
                                .AllowAnyMethod()
                                .AllowAnyHeader());

额外的标题是因为,根据文档:

  

浏览器在设置Access-Control-Request-Headers方面并不完全一致。如果您将标题设置为“*”以外的任何标题,则应至少包含“accept”,“content-type”和“origin”,以及您要支持的任何自定义标题。

答案 1 :(得分:6)

仅在以下情况下返回Access-Control-Allow-Origin标头:

  1. 请求包含“Origin”标题。
  2. 请求的来源与CORS政策相符。
  3. 然后服务器返回带有原始URL的ACAO标头作为值。

    Origin标头通常由XMLHttpRequest对象设置。

    有关详细信息,请参阅How CORS works

答案 2 :(得分:1)

在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 {}  

答案 3 :(得分:1)

我想为那些遵循以上建议但仍无法正常工作的人增加一种可能性。就我而言,由于管道中的注册顺序,我没有得到标头的返回(或仅在第一个请求时才得到标头)。

我从此更改了顺序:

app.UseResponseCaching();
app.UseHttpsRedirection();
app.UseCors("WideOpen");
app.UseMvc();

对此:

app.UseCors("WideOpen");
app.UseResponseCaching();
app.UseHttpsRedirection();
app.UseMvc();

那解决了我的问题。

答案 4 :(得分:1)

我今天在这个问题上浪费了小时,结果发现这是因为如果您使用启用 CORS 的端点路由 RequirePolicy 方法,.Net Core 3 不支持预检 OPTIONS 请求!

official documentation 确实提到了这一点,但没有在明显的警告块中提到它,所以我完全错过了。

以下内容将解决该问题,但它将应用全局 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();
    });
...

答案 5 :(得分:0)

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("*"));

答案 6 :(得分:-1)

As of date 03/17/2019, .NET Core version 2.1:

This will possibly save some time to other poor souls...at some point I started to be frustrated and almost gave up on .NET Core WebApi as a separate project.

In real life circumstances, there are other configurations in Startup functions e.g. I had Swagger, DI registrations etc. I wasn't able to make bloody thing work until I put both AddCors() and UseCors() methods to be the first one getting called in configuration functions.

 // 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");

After that, calls from Angular 6 app (Swagger Typescript client calls) started to work as a charm.