.net core 2.2 和广泛开放的 CORS

Posted

技术标签:

【中文标题】.net core 2.2 和广泛开放的 CORS【英文标题】:.net core 2.2 and wide open CORS 【发布时间】:2019-09-14 16:56:11 【问题描述】:

从 .net core 2.2 开始,我们不能同时接受所有来源并接受凭据。虽然它解决了安全问题,但在某些情况下我们并不关心并且希望事情大开。

所以,我在几个线程上找到的建议解决方案是:

    Services.AddCors(CorsOptions =>
    
        CorsOptions.AddPolicy("AllowAll", P =>  P
            .SetIsOriginAllowed(_ => true)
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials();
        );
    );

但这仍然会出现以下错误:

对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。

对于使用 2.2 的广泛开放的 CORS,什么是可行的解决方案?

【问题讨论】:

【参考方案1】:

我认为您所需要的只是@Praneet 提到的以下内容。创建一个所有访问策略

services
    .AddCors(options => options
        .AddPolicy("WideOpen", p => p
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader())
    );

您还需要在 Configure 方法中添加一行来全局启用它

public void Configure(IApplicationBuilder app, IHostingEnvironment env)

    app.UseCors("WideOpen");

更新答案

services
    .AddCors(options => options
        .AddPolicy("WideOpen", p => p
            .SetIsOriginAllowedToAllowWildcardSubdomains()
            .WithOrigins("*")
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials())
    );

根据documentation SetIsOriginAllowedToAllowWildcardSubdomains 是允许的来源所必需的。所以我设置WithOrigins 使用通配符

更新答案 2

好的,我知道你的问题了。我不认为这是一个理想或推荐的解决方案,但它会起作用。你可以有一个中间件,它为每个请求注入响应标头,这些标头是允许 AnyOrigin、AnyMethod 和 AnyHeader 以及凭据所必需的。但是,它只会为请求中存在的 Origin 添加 Access-Control-Allow-Origin 标头,因此允许任何来源。

如果 Ajax 检查不起作用,您可以将其删除。唯一的缺点是,它将为所有请求注入标头。

public class WideOpenCorsMiddleware

    private readonly RequestDelegate _next;

    public WideOpenCorsMiddleware(RequestDelegate next)
    
        _next = next;
    

    public async Task Invoke(HttpContext context)
    
        var response = context.Response;

        // check if it's an ajax request
        if (context.Request.Headers != null && context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
        
            response.Headers.Add("Access-Control-Allow-Origin",
                new[]  (string)context.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[]  "GET, POST, PUT, DELETE, OPTIONS" );
            response.Headers.Add("Access-Control-Allow-Credentials", new[]  "true" );
            response.StatusCode = 200;
        

        // if not a pre-flight request
        if (context.Request.Method != "OPTIONS")
        
            await _next(context);
        
    

你也可以有这个Extension方法,所以你可以很方便的在Configure方法中使用。

// Extension method used to add the middleware to the HTTP request pipeline.
public static class MiddlewareExtensions

    public static IApplicationBuilder UseWideOpenCors(this IApplicationBuilder builder)
    
        return builder.UseMiddleware<WideOpenCorsMiddleware>();
    

最后,在Configure 方法中,添加以下行,可能在顶部:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)

    app.UseWideOpenCors();

【讨论】:

这将起作用,但没有 AllowCredentials,因此不允许使用 cookie。自 .net core 2.2 起,不再允许 AllowAnyOrigin 和 AllowCredentials 一起使用;所以要么你需要列出来源,要么你不能收到cookies。直到 .net core 2.1,它都很好。我需要的是找到如何在 2.2 下做出 2.1 的行为 好的,我自己没有测试过,但是看看更新后的答案是否适合你 这是旧的 2.1 方法,在 2.2 中不再适用 看来你运气不好。看看this 和this 也许,您需要从某个地方读取来源,但这意味着您需要将它们添加到某个地方,也可以在某个数据库中。一种选择是使用将检查请求并将其作为允许的来源添加到 CORS 策略的中间件。该策略将在运行时更新。请看看这个post。虽然在这篇文章中,策略是使用 origins 控制器更新的。但是,您可以使用类似的方法并在中间件中注入ICorsPolicyAccessor。我希望这会有所帮助【参考方案2】:

在您的 appsettings.json 中添加您的 cors 来源。像这样的:

"CorsOrigins": 
    "Urls": [ "http://localhost:4200", "http://localhost:8090", "https://localhost:44376" ]
  

然后像这样设置你的启动:

var corsOriginsSection = Configuration.GetSection("CorsOrigins");
var origins = corsOriginsSection.Get<CorsOrigins>();

services.AddCors(options => options.AddPolicy("AllowSpecificOrigin", p => p.WithOrigins(origins.Urls)
                                               .AllowAnyMethod()
                                               .AllowAnyHeader()));

然后在你的控制器上添加这个:

 [EnableCors("AllowSpecificOrigin")]

应该可以。

我要使用的类是这样的:

public interface ICorsOrigins

    string[] Urls  get; set; 

public class CorsOrigins : ICorsOrigins

    public string[] Urls  get; set; 

我会将来源保留在 appsettings 中,否则它将是硬编码的东西。

就像特定来源一样,创建一个政策 All Access 并根据您的要求使用它

【讨论】:

这正是我想要避免的:我想让 CORS 完全开放:任何客户端、任何方法、任何标头、所有 cookie、没有检查、没有安全性、允许一切和所有人 :) 我可以'不列出客户,因为我们不认识他们 这就是为什么我说就像特定来源一样,创建一个所有访问策略并根据您的要求使用它为什么不尝试使用 Identity Server。 但是在那个策略中,你需要设置来源吗?我不需要身份服务器,我们使用 JWT 允许访问短期一次性帐户,因此这些帐户绝对没有任何价值,任何想浪费时间的人都可以入侵。但是由于我们通过浏览器,我们需要通过 cookie(对于 JWT)并允许任何来源(因为在调用之前我们不知道来源)

以上是关于.net core 2.2 和广泛开放的 CORS的主要内容,如果未能解决你的问题,请参考以下文章

CORS预检请求被阻止.Net Core 2.2 [重复]

从 2.2 .Net core 迁移到 3.0 Cors 错误

如何为 ASP.NET Core 2.2 项目中的子域正确启用 CORS?

本地 Javascript Fetch Post 请求失败,调用 ASP.NET Core 2.2 Web API。 CORS 已启用

ASP.NET Core 2.2 CORS 没有“Access-Control-Allow-Origin”标头 [关闭]

EnableCors C# .NET Core 3