【问题标题】:.net core api CORS Get works but cors gets 405.net core api CORS 获得工作,但 cors 获得 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

标签: c# .net 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");
                });
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2017-04-14
          • 2012-08-10
          • 2019-10-09
          • 2018-07-15
          • 2021-09-14
          • 2017-11-21
          • 2020-05-22
          • 2018-06-29
          • 2019-10-18
          相关资源
          最近更新 更多