.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 前端