你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

ASP.NET Core 配置跨域(CORS)

2021-11-2 0:08:35

由于项目中需要实时消息,所以就使用了ASP.NET(Core) SignalR实时通讯库。因为业务服务与通讯服务是独立的,所以涉及到跨域的问题, 浏览器抛出的异常非常明显,这个是明显跨域相关内容。 报错信息如下:
在这里插入图片描述

Access to XMLHttpRequest at ‘http://192.168.2.13:5005/api/v1/commommessage/messageHub/negotiate’ from origin ‘http://127.0.0.1:5500’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

CORS(跨域资源共享)是一种W3C标准,允许服务器放宽同源策略。使用CORS,服务器可以在显式允许某些跨域请求时拒绝其他跨域请求。CORS是相比其他跨域技术(比如JSONP)更安全、更灵活。

ASP.NET Core跨域问题需要再 StartUp.cs 文件中进行相关配置。

ConfigureServices方法增加内容

services.AddCors(options => options.AddPolicy("CorsPolicy",
    builder =>
    {
        builder.AllowAnyMethod()
            .AllowAnyHeader()
            .AllowAnyOrigin()
            .AllowCredentials();
    }));

完整的ConfigureServices方法示例如下:

 
public IServiceProvider ConfigureServices(IServiceCollection services)
{
 
    services.AddCors(options => options.AddPolicy("CorsPolicy",
        builder =>
        {
            builder.AllowAnyMethod()
                .AllowAnyHeader()
                .AllowAnyOrigin()
                .AllowCredentials();
        }));
 
    services.AddMvc(options => { options.Filters.Add(); })
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
        //全局配置Json序列化处理
        .AddJsonOptions(options =>
        {
            options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
        })
        .AddFluentValidation();
 
    services.AddSignalR();
 
    return services.AutofacServiceProvider();
}

Configure方法中添加

app.UseCors("CorsPolicy");

完整Configure方法示例:

 
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
                      ILoggerFactory loggerFactory,
                      IOptions config)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    if (env.IsProduction())
    {
        //注册服务到consul
        app.UseConsul();
 
        using (HttpClient client = new HttpClient())
        {
            StringContent content = new StringContent(JsonConvert.SerializeObject(config.Value.RegisterParams));
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            HttpResponseMessage message = client.PostAsync(config.Value.Server.Address, content).Result;
        };
    }
    app.UseCors("CorsPolicy");
    loggerFactory.AddNLog();
    env.ConfigureNLog("nlog.config");//读取Nlog配置文件
    app.UseSignalR(routes =>
    {
        routes.MapHub("/api/v1/examinations/messageHub");
    });
    app.UseMvc();
}

特别注意:app.UseCors()必须放在app.UseMvc()之前。

本以为这就算完了,但是万万没想到啊,依然没有什么用。浏览器控制台错误依然存在,.net core也提示了相关警告信息,差点就忘了现在使用.net core 版本和以前不一样了。

The CORS protocol does not allow specifying a wildcard (any) origin and credentials at the same time. Configure the policy by listing individual origins if credentials needs to be supported.

在这里插入图片描述

目前使用的是ASP.NET CORE 2.1, 其Cors组件已经升级,出于安全考虑必须明确要允许的内容。 这是安全的一部分,你不能这样做。 如果要允许凭据,则Access-Control-Allow-Origin不能使用*。 您必须指定确切的协议+域+端口。

这个问题其实也很好解决,只需要给予一个可信列表即可。修改内容如下:

services.AddCors(options => options.AddPolicy("CorsPolicy",
    builder =>
    {
        builder.WithOrigins(new string[] { "http://127.0.0.1:5500" })
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials();
    }));

如果真的就不想做任何限制,其实也是有办法的。只需要将AllowAnyOrigin替换为SetIsOriginAllowed(_ => true)就可以解决。

   services.AddCors(options => options.AddPolicy("CorsPolicy",
        builder =>
        {
            builder.AllowAnyMethod()
                .SetIsOriginAllowed(_ => true)
                .AllowAnyHeader()
                .AllowCredentials();
        }));

除了前面的两个方法以外,其实还可以自定义中间件。添加Cors处理类。如下:

public class CorsMiddleware
{
    private readonly RequestDelegate next;
 
    public CorsMiddleware(RequestDelegate next)
    {
        this.next = next;
    }
    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Headers.ContainsKey(CorsConstants.Origin))
        {
            context.Response.Headers.Add("Access-Control-Allow-Origin", context.Request.Headers["Origin"]);
            context.Response.Headers.Add("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS,HEAD,PATCH");
            context.Response.Headers.Add("Access-Control-Allow-Headers", context.Request.Headers["Access-Control-Request-Headers"]);
            context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
 
            if (context.Request.Method.Equals("OPTIONS"))
            {
                context.Response.StatusCode = StatusCodes.Status200OK;
                return;
            }
        }
 
        await next(context);
    }
}

Configure方法中添加如下内容即可

app.UseMiddleware<CorsMiddleware>();