简体   繁体   English

在 ASP.Net Core 5 WebAPI 中启用 CORS

[英]Enable CORS in ASP.Net Core 5 WebAPI

There are millions of articles and questions related to this issue and yet I cannot find what's wrong with my code.有数百万篇与此问题相关的文章和问题,但我找不到我的代码有什么问题。 I have Startup , StartupProduction , and StartupDevelopment as the following.我有StartupStartupProductionStartupDevelopment ,如下所示。 Also, I am using ASP.Net Core 5 , and based on the documentation I think I am doing this correctly.另外,我正在使用ASP.Net Core 5 ,并且根据文档,我认为我这样做是正确的。

FYI, at first, I used AllowAnyOrigin for development but I also test .WithOrigins("http://localhost:3000") and it works fine.仅供参考,起初,我使用AllowAnyOrigin进行开发,但我也测试.WithOrigins("http://localhost:3000")并且它工作正常。 My backend runs under https://localhost:44353 in development and under https://api.example.com in production.我的后端在开发中在https://localhost:44353下运行,在生产中在https://api.example.com下运行。

public class Startup
{
    protected const string CorsPolicyName = "CorsPolicyName";

    public virtual void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers()
            .AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.Converters.Add(
                    new System.Text.Json.Serialization.JsonStringEnumConverter());
            });

        services.AddABunchOfOtherServices();
    }

    public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();
        app.UseCors(CorsPolicyName);
        app.UseAuthentication();
        app.UseAuthorization();

        app.UseMiddleware<CheckUserConfirmedMiddleware>();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute
            (
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}"
            )
            .RequireCors(CorsPolicyName);
        });
    }
}

public class StartupProduction : Startup
{
    public override void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(
                CorsPolicyName,
                policy => policy
                    .WithOrigins("https://example.com", "http://example.com")
                    //.WithOrigins(Configuration.GetValue<string>("AllowedHosts").Split(';').ToArray())
                    .AllowAnyMethod()
                    .AllowAnyHeader());
        });

        base.ConfigureServices(services);
    }

    public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseMiddleware(typeof(ErrorHandlingMiddleware));

        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();

        base.Configure(app, env);
    }
}

public class StartupDevelopment : Startup
{
    public override void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
            options.AddPolicy(
                CorsPolicyName,
                policy =>
                    policy
                        //.AllowAnyOrigin()
                        .WithOrigins("http://localhost:3000")
                        .AllowAnyMethod()
                        .AllowAnyHeader()
            )
        );

        base.ConfigureServices(services);

        services.AddSwaggerGen(....);
    }

    public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseMiddleware<DevelopmentErrorHandlingMiddleware>();

        base.Configure(app, env);

        app.UseSwagger();

        app.UseSwaggerUI(options =>
        {
            options.SwaggerEndpoint("swagger/v1/swagger.json", "API v1");
            options.RoutePrefix = string.Empty;
        });
    }
}

I also tried the default policy .我还尝试了默认策略

Update更新

I have set the Environment to Production in the visual studio to debug it and now I am facing the same issue in development.我已在 Visual Studio 中将Environment设置为Production以对其进行调试,现在我在开发中面临同样的问题。

Access to fetch at 'https://localhost:44353/api/v1/User' from origin 'http://localhost:3000' 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 策略已阻止从源“http://localhost:3000”获取“https://localhost:44353/api/v1/User”的访问权限:对预检请求的响应未通过访问控制检查:否'Access-Control-Allow-Origin' header 存在于请求的资源上。 If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源。

Workaround solution解决方法

I notice that it is the IIS blocking the request.我注意到是 IIS 阻止了请求。 It only works when I have "AllowedHosts": "*", in my appsettings.json .它仅在我的 appsettings.json 中有"AllowedHosts": "*", appsettings.json So, as a workaround, I have added "MyRandomKey": "https://example.com", in my appsettings.json and use the following in my Startup .因此,作为一种解决方法,我在我的 appsettings.json 中添加了“ appsettings.json "MyRandomKey": "https://example.com",并在我的Startup中使用以下内容。

services.AddCors(options =>
                options.AddPolicy(
                    CorsPolicyName,
                    policy =>
                        policy
                            .WithOrigins(Configuration.GetValue<string>("MyRandomKey").Split(";").ToArray())
                            .AllowAnyMethod()
                            .AllowAnyHeader()
                )
            );

AllowedHosts & CORS are different. AllowedHosts 和 CORS 是不同的。

AllowedHosts is for host filtering so even if you have configured CORS Policy in your application but didn't allowed host then IIS will reject the request. AllowedHosts 用于主机过滤,因此即使您在应用程序中配置了 CORS 策略但不允许主机,IIS 也会拒绝该请求。

Please refer this link: Difference between AllowedHosts in appsettings.json and UseCors in .NET Core API 3.x请参考此链接: Difference between AllowedHosts in appsettings.json and UseCors in .NET Core API 3.x

And by default it's * but you can change it to according to your requirements.默认情况下它是 * 但您可以根据您的要求将其更改为。 In your case you can set "api.example.com" or if you want to allow also from localhost then "api.example.com;localhost".在您的情况下,您可以设置“api.example.com”,或者如果您也想从 localhost 允许,那么“api.example.com;localhost”。 Once you set it then IIS will start accepting requests from those domains.一旦你设置了它,那么 IIS 将开始接受来自这些域的请求。

Once IIS will start accepting request then your application level configured CORS policy will be applied and work.一旦 IIS 将开始接受请求,那么您的应用程序级别配置的 CORS 策略将被应用并工作。 So basically the CORS is to allow access of resources in your WebAPI.所以基本上 CORS 是允许访问 WebAPI 中的资源。

I think it's Ok, and also, you can get origins from DB or JSON files.我认为没关系,而且,您可以从 DB 或 JSON 文件中获取来源。 also, you can use ActionFilterAttribute and this part of the code此外,您可以使用 ActionFilterAttribute 和这部分代码

    var csp = "default-src 'self' http://localhost:3000; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';";

if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy"))
{
    context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp);
}

if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy"))
{
    context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp);
}

From this doc about CORS preflight request , you can find following information:这个关于 CORS 预检请求的文档中,您可以找到以下信息:

A CORS preflight request is used to determine whether the resource being requested is set to be shared across origins by the server. CORS 预检请求用于确定所请求的资源是否设置为由服务器跨源共享。 And The OPTIONS requests are always anonymous, server would not correctly respond to the preflight request if anonymous authentification is not enabled.并且 OPTIONS 请求始终是匿名的,如果未启用匿名身份验证,服务器将无法正确响应预检请求。

Access to fetch at 'https://localhost:44353/api/v1/User' from origin 'http://localhost:3000' 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 策略已阻止从源“http://localhost:3000”获取“https://localhost:44353/api/v1/User”的访问权限:对预检请求的响应未通过访问控制检查:否'Access-Control-Allow-Origin' header 存在于请求的资源上。 If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源。

To fix the above issue, if you run the App(s) on local for testing purpose with CORS, you can try to enable anonymous authentification.要解决上述问题,如果您使用 CORS 在本地运行应用程序以进行测试,您可以尝试启用匿名身份验证。

Besides, if your App(s) are hosted on IIS, you can try to install IIS CORS module and configure CORS for the app.此外,如果您的应用程序托管在 IIS 上,您可以尝试安装IIS CORS 模块并为应用程序配置 Z5A8ZFF0B76024BDEB3EEC9D924。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM