繁体   English   中英

.net core api CORS 得到工作但 cors 得到 405

[英].net core api CORS Get works but cors gets 405

我有以下中间件:

    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错误:

在此处输入图片说明

您需要为 CORS 预检请求发送状态代码 200,您的中间件现在没有设置。

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

在这里 ,

https://localhost:5001/api/WorkTimes

当通过GET HTTP方法请求发送有效凭据时,服务器使用它来返回特定数据集。因此,在这种情况下,服务器在该资源/URL 上接受POST请求是没有意义的,因此它可能发出此类请求时,以405(不允许方法)状态代码响应。

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();
        });
}

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

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

铬不支持这一点。

​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 

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

在许多情况下可以解决问题。 您可以在此处为chrome 上的此功能点赞

解决方案2(推荐)

在子域下创建您的api

你的 api url 将是http://localhost:4200/api/YourEndpoint

这里
Voyage是我们的角度应用程序。
在它的Api下,我们托管我们的 API,因此它们将位于同一域下,因此不会违反 CORS 政策。
IIS 设置

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 Middlewares。 为什么要重新发明轮子?

这是Asp.Net Core v2.1 Cors Middleware的示例

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");
        });
    }
}

暂无
暂无

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

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