.net core api CORS 获得工作,但 cors 获得 405

Posted

技术标签:

【中文标题】.net core api CORS 获得工作,但 cors 获得 405【英文标题】:.net core api CORS Get works but cors gets 405 【发布时间】:2020-04-12 23:50:22 【问题描述】:

我有以下中间件:

    namespace TimeManagement

    public class CorsMiddleware
    
        private readonly RequestDelegate _next;

        public CorsMiddleware(RequestDelegate next)
        
            _next = next;
        

        public Task Invoke(HttpContext httpContext)
        
            httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
            httpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            httpContext.Response.Headers.Add("Access-Control-Allow-Headers",
                "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
            httpContext.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
            return _next(httpContext);
        
    

// Extension method used to add the middleware to the HTTP request pipeline.
    public static class CorsMiddlewareExtensions
    
        public static IApplicationBuilder UseCorsMiddleware(this IApplicationBuilder builder)
        
            return builder.UseMiddleware<CorsMiddleware>();
        
    

还有以下startup类:

namespace TimeManagement

    public class Startup
    
        public Startup(IConfiguration configuration)
        
            Configuration = configuration;
        

        public IConfiguration Configuration  get; 

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        
            services.AddDbContext<WorkTimeContext>(opt =>
                opt.UseInMemoryDatabase("WorkTime"));
            services.AddDbContext<TimeManagementContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("TimeManagementContext")));

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
            services.AddControllers();
        

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        
            if (env.IsDevelopment())
            
                app.UseDeveloperExceptionPage();
            

            app.UseHttpsRedirection();
            app.UseCorsMiddleware();
            app.UseRouting();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>  endpoints.MapControllers(); );
        
    

然后我尝试运行https://localhost:5001/api/WorkTimes GET,它返回没有问题。

现在我正在使用Angular 前端,并从那里尝试发布。您可能知道,它首先发送OPTIONS,然后我收到CORS 错误:

【问题讨论】:

请注意,如果您也接受身份验证,则不能使用 * 作为 Origins 标头。如果您使用 auth,则需要完全指定 Origins 标头,而不是通配符。请参阅MDN,向下滚动到“凭据请求和通配符”。我不认为这是您的问题的原因,但它会在某些时候影响您。 你如何部署你的api?您是否考虑过使用内置的 cors 中间件docs.microsoft.com/en-us/aspnet/core/security/cors? 【参考方案1】:

您需要为 CORS 预检请求发送状态码 200,而您的中间件目前未设置。

您为什么不直接使用处理此问题的 ASP.NET CORS 中间件? ASP.NET CORS Middleware

【讨论】:

【参考方案2】:

在这里,

https://localhost:5001/api/WorkTimes

被服务器用来在通过GET HTTP方法请求发送有效凭证时返回特定的数据集。因此,在这种情况下,服务器接受POST 该资源/URL 的请求,因此在发出此类请求时,它可能会以 405(Method Not Allowed) 状态代码进行响应。

405(Method Not Allowed) 是一个 HTTP 响应状态码,表明指定的请求 HTTP 方法已被服务器接收并识别,但服务器拒绝了请求资源的特定方法。405 码响应确认请求的资源有效且存在,但客户端在请求期间使用了不可接受的 HTTP 方法。

这可能在几种不同的情况下发生:

用户代理意外发送了错误的 HTTP 方法。 服务器只期望少数有效的 HTTP 方法用于 请求的资源。

使用下面的 ASP.NET CORS 中间件代替自定义中间件。(Asp.Net Core v3.0 示例代码)

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

     if(env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
        

        app.UseHttpsRedirection();

        app.UseCors(cor=> cor
           .AllowAnyHeader()
           .WithOrigins("http://localhost:4200","https://localhost:4200"));

        app.UseRouting();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        
          endpoints.MapControllers();
        );

【讨论】:

【参考方案3】:

您可以尝试将以下内容放入 web.config:

<httpHandlers>
  ... 
    <add path="*" verb="OPTIONS" type="System.Web.DefaultHttpHandler" validate="true"/>
</httpHandlers>

【讨论】:

@Gaurvasa 我没有 web.config 文件?【参考方案4】:

chrome 不支持这个。

​Access to XMLHttpRequest at '...' from origin '...' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

方案一 [临时开发方案]

chrome://flags/#out-of-blink-cors 

禁用 out-of-blink-cors 标志,方法是将该地址复制并粘贴到 Chrome 的地址栏中,然后按 [enter]。在打开的页面中,您会看到一个突出显示的所谓“标志”(实验)。禁用它并重新启动 Chrome (编辑:之前我说过要启用标志,但似乎只有禁用才有效)

在许多情况下可以解决问题。 您可以在 chrome here

上投票支持此功能

解决方案 2(推荐)

在子域下创建你的api

您的 api 网址将是 http://localhost:4200/api/YourEndpoint

Voyage 是我们的 Angular 应用程序。 在它的 Api 下,我们托管我们的 API,因此它将在同一个域下,因此不会违反 CORS 政策。

【讨论】:

【参考方案5】:

Cors 错误可能非常狡猾。有时浏览器会在没有真正调用您的 api 的情况下返回此错误。所以第一步你需要确保浏览器调用你的API。为此,我通常会添加一个愚蠢的内联中间件并在其中放置一个断点。你也可以给它添加一个记录器。

愚蠢的中间件示例:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)

    app.Use(async (context, next) =>
    
        await next.Invoke();
        // Do logging or other work that doesn't write to the Response.
    );

    // The others middlewares.

既然您知道问题出在您的浏览器还是您的应用程序中,您可以做什么?

1) 如果问题出在您的浏览器中,请按照@Eldho 回答中的说明启用它。

2) 如果问题出在您的应用程序中,请阅读我的其余答案。

中间件的执行顺序与您在 Configure 方法中调用它的顺序相同。

也许HttpsRedirection 正在返回此错误。 (可能在这里大)

您可以尝试在HttpsRedirection 之前声明您的自定义app.UseCorsMiddleware()。但我建议您使用已经存在且工作正常的 Asp.net Cors 中间件。为什么要重新发明***?

这是 Asp.Net Core v2.1 Cors 中间件的示例

public void ConfigureServices(IServiceCollection services)

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


public void Configure(IApplicationBuilder app, IHostingEnvironment env)

    app.UseCors("Any");
    // The others middlewares.

另一种方法(仅用于开发)是使用 SPA 中间件 将请求转发到您的 SPA。这样,您的 Angular 应用程序和您的 Asp.Net 应用程序将在 localhost 的同一端口上响应,并且 chrome 不会阻止任何内容。但它只是作为临时解决方案。不建议在生产中使用它。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)

    app.UseCors("Any");

    // The others middlewares.

    if (env.IsDevelopment())
    
        app.UseSpa(spa =>
        
            spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
        );
    

【讨论】:

以上是关于.net core api CORS 获得工作,但 cors 获得 405的主要内容,如果未能解决你的问题,请参考以下文章

如何让 CORS 与 ASP.Net Core Web API 服务器 Angular 2 客户端一起工作

.Net core2 CORS - SetIsOriginAllowed 如何工作?

CORS 不适用于 .NET Core API 和 Angular 前端

.NET Core CORS 策略块

根据官方文档,Asp.net Core 3.0 CORS 无法正常工作

仅在一个 .Net Core 2.0 Web API 控制器上出现 CORS 错误