405(方法不允许)和CORS策略阻止。

7
我有一个基于 Angular(7.2.1) 的客户端的 Asp.Net Core(3) WebApi 项目。当使用 Postman 或直接使用 URL 时,我可以使用 GET 和 POST,没有任何错误。 但是当我试图在 Angular (Chrome\FireFox\IE 浏览器) 中尝试相同操作时,我会遇到以下错误:

zone.js:3243 OPTIONS http://localhost:8888/api/PaymentDetails 405 (Method Not Allowed) 从源 'http://localhost:4200' 到 'http://localhost:8888/api/PaymentDetails' 的 XMLHttpRequest 访问由于 CORS 策略而被阻止: 预检请求的响应不通过访问控制检查: 所请求的资源未包含 'Access-Control-Allow-Origin' 头。

我将尽可能共享代码以演示流程。

WebApi Startup.cs:

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.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder =>
            builder.AllowAnyOrigin()
                   .AllowAnyMethod()
                   .AllowAnyHeader()

                );
    });
    services.AddControllers()
        .AddJsonOptions(options =>
        {
            options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
            options.JsonSerializerOptions.PropertyNamingPolicy = null;
        });

    services.AddDbContext<PaymentDetailContext>(options => options.UseSqlServer("Server=DESKTOP-KT0N2RN\\SQLEXPRESS;DataBase=PaymentDetailDB;Trusted_Connection=True;MultipleActiveResultSets=True;"));
}

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

    app.UseAuthorization();

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

    app.UseCors("CorsPolicy");
}

WebAPI GET方法:

[HttpGet]
public async Task<ActionResult<IEnumerable<PaymentDetail>>> GetPaymentDetails()
{
    return await _context.PaymentDetails.ToListAsync();
}

客户端:

rootUrl: string = "http://localhost:8888/api";

getPaymentDetail()
{
    
    console.log(`${this.rootUrl}/PaymentDetails`)
    const headers = new HttpHeaders().set('Content-Type','application/json');
    // headers.append('Access-Control-Allow-Origin', '*');
    // headers.append('Access-Control-Allow-Headers','Origin, X-Requested-With, Content-Type, Accept');
    return this._http.get(`${this.rootUrl}/PaymentDetails`,{headers:headers});
}

请查看此答案 https://dev59.com/ZlwZ5IYBdhLWcg3wBcWz - Muhammed Albarmavi
我更新了我的答案,希望现在能够正确地解决你的问题。 - Kevin
1
是的,这里的一个答案帮助我解决了问题。app.UseCors()必须在app.UseMvc()之前。 - JumpIntoTheWater
2个回答

14
我认为在Startup Configure中更改以下内容应该可以解决问题。请注意顺序:根据文档

使用端点路由时,CORS中间件必须配置为在调用UseRouting和UseEndpoints之间执行。配置不正确将导致中间件无法正常工作。

app.UseRouting();

app.UseAuthorization();

app.UseCors("CorsPolicy");

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

我认为对于CORS的一个快速概述可能有助于解释为什么Postman请求对您有效。
默认情况下,浏览器使用CORS检查服务器将接受哪些来源的请求。
如果您对服务器的请求来自相同的来源(所有来源的所有部分必须匹配),则您的CORS请求不会失败,因为它不是跨域。在您的情况下,端口不匹配,因此即使服务器和Web应用程序都从本地主机运行,也会被视为跨域。
当您发送请求时,浏览器将首先发送Options请求(预检请求),该请求将显示支持的方法并检查您的来源(前端Web应用程序)是否有权向服务器发送请求。这个功能默认内置于大多数主流浏览器中(Chrome、Firefox、Edge等)。
您的Postman请求有效,因为Postman不发送预检请求。
进一步阅读:
启用CORS

https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1

CORS是什么

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS


2
问题在于我在 app.UseMvc 之后使用了 app.UseCors() - JumpIntoTheWater
很高兴你已经解决了。app.UseMvc(); 在代码片段中没有出现,所以当我提到顺序时我把它省略了。有用的提示:始终将 app.UseMvc(); 放在最后调用,这将有助于避免中间件问题。 - Kevin
我知道顺序很重要,但我还是花了几个小时来弄清楚这个问题。我原以为 app.UseCors("CorsPolicy") 应该放在 app.UseAuthorization 之前。看来不是这样。跨域总是个麻烦。 - undefined

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接