【问题标题】:.NET Core UseCors() does not add headers.NET Core UseCors() 不添加标头
【发布时间】:2017-06-10 04:24:30
【问题描述】:

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

我试图在我的 .NET Core Web API 的响应中获取一个 Access-Control-Allow-Origin 标头,我通过 AJAX 访问它。

我已经尝试了几件事。除非另有说明,否则所有内容都在 Startup.cs 文件中。

方法一

根据Microsoft Documentation

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

方法二

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
日期 → 2017 年 1 月 25 日星期三 04:51:48 GMT
服务器 →Kestrel
状态 → 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()
    {
        // ...
    }
}

【问题讨论】:

  • 您如何使用 Postman 访问服务器?仅针对 OPTIONS 请求返回标头
  • @Rob。这就是我所缺少的。在 Postman 方面较少(我也曾在 Chrome 中尝试过,并且使用了正确的方法),而在控制器方面则更多。我有[HttpGet] 而不是[HttpOptions]。我有一种感觉,它会像那样愚蠢。
  • @Rob,但是,Chrome 仍然失败。它收到 204 错误。邮递员完美地工作。两者都使用相同的 Bearer 令牌。 Chrome 中的缓存已禁用。
  • 那.. 对我来说似乎不正确。您不必将控制器方法标记为HttpOptions。您在方法 1 中的代码看起来是正确的(刚刚检查了我的本地项目,该项目有效)。我觉得 chrome 失败了,因为它缓存了飞行前的 OPTIONS 请求,而邮递员失败了,因为您没有发送 OPTIONS 请求。
  • 即使缓存被禁用,您是否可以检查您的网络日志并检查是否实际发送了 OPTIONS 预检?

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


【解决方案1】:

问题在于,当使用 Bearer 身份验证(或我想像的任何身份验证)时,它会添加一个标头“授权”,并且只有在设置允许该标头时服务器才会允许。

有两种方法可以解决这个问题,下面是需要的代码。它进入 Web API 解决方案中 Startup.cs 中的 Configure() 方法。

方法一:允许所有标头

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”,以及您想要支持的任何自定义标头。

【讨论】:

    【解决方案2】:

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

    1. 请求包含“Origin”标头。
    2. 请求的来源符合 CORS 政策。

    然后服务器以原始 URL 作为值返回 ACAO-header。

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

    欲了解更多信息,请参阅How CORS works

    【讨论】:

    • 这些信息对我有帮助。我确实正确设置了所有内容,但是在testing with cURL 时忘记发送Origin 标头。
    • 非常感谢您。我花了几个小时才让它工作,结果我的配置是正确的,但测试应用程序没有发送来源
    • 谢谢,遇到了和nightblade9一样的问题!
    【解决方案3】:

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

    [禁用Cors]
    使用 DisableCors 属性,我们可以为控制器或动作禁用 CORS。

    //启用CORS控制器基础 - 如果你全局应用你不需要这个。

    [EnableCors("AllowAllOrigins")]  
    public class HomeController: Controller {}  
    

    【讨论】:

    • 是否值得在这里添加,添加所有来源将是不安全的(有效禁用 Cors),最好只指定您想要允许的来源以避免跨站点脚本的可能?跨度>
    【解决方案4】:

    截至 2019 年 3 月 17 日,.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 客户端调用)开始发挥作用。

    【讨论】:

    • @David 如果在您的 Setup.cs 中您只有 CORS 设置,那么没有区别。但是,您更有可能拥有用于错误的中间件、Facebook、Swagger ......在这种情况下,CORS 启用功能必须是管道中的第一个功能/在配置功能中调用。否则,它可能无法正常工作。请注意, UseMvc() 也必须追随它,但在我看到的很多文章中都提到了它。我的观点是;必须小心使用这些代码行的位置和上下文。
    • 我已经为此苦苦挣扎了好几个小时了。我到处都看到过这种方法的详细说明,但无论我做什么,我都没有得到 CORS 标头。我只希望将这些标题附加到每个响应中,但从人们所说的来看,这是一项非常复杂的任务!
    • 这是给我的。文件上传正确,但浏览器仍在抱怨。在配置中以正确的顺序交换行修复了它。 app.UseCors("AllowAllOrigins") |> 忽略; app.UseGiraffe 路线
    【解决方案5】:

    我今天在这个问题上浪费了 小时 才发现这是因为如果您使用启用 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();
        });
    ...
    

    【讨论】:

    • 我并没有完全按照你说的去做,但我做的事情有那么糟糕吗? app.UseEndpoints(endpoints =&gt; { endpoints.MapDefaultControllerRoute().RequireAuthorization(); });
    【解决方案6】:

    我想为那些可能已经遵循上述建议但仍然无法正常工作的人再添加一种可能性。在我的情况下,由于管道中的注册顺序,我没有返回标头(或仅在第一次请求时获得)。

    我从这里更改了顺序:

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

    到这里:

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

    这解决了我的问题。

    【讨论】:

      【解决方案7】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-19
        • 2020-03-12
        • 2019-11-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多