我用一个控制器创建了一个ASP.Net CORE Web API项目,现在想从客户端(反应)Web应用程序中调用它。
但是,调用失败,并且“所请求的资源上没有'Access-Control-Allow-Origin'标头。”
从Fiddler调用同一端点时,预期的响应头不存在。
多亏了ATerry,我有了进一步的了解:标头不存在,因为React Web应用程序和.Net Core Web API托管在同一个盒子中。 React填充了请求Origin:标头,该标头与(API)框相同,因此服务器(真的很聪明)不会添加Allow -...响应标头。但是,由于缺少这些标头,React应用拒绝了响应。
我正在使用.Net Core v2.1(本文撰写时为最新)。
我基于
构建了代码https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1
我检查了这些
https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas
How to enable CORS in ASP.NET Core
...但是所有建议都没有。
有什么想法吗?
这是我配置.Net Core应用程序的方式(代码从实际更改为尝试并允许任何操作):
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)
{
// Enable CORS (Cross Origin Requests) so that the React app on a different URL can access it
// See https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1
services.AddCors(options =>
{
options.AddPolicy(Global.CORS_ALLOW_ALL_POLICY_NAME, builder => builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials());
});
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors(Global.CORS_ALLOW_ALL_POLICY_NAME);
app.UseHttpsRedirection();
app.UseMvc();
}
}
由于上述原因而失败,我也将CORS属性添加到控制器类和控制器方法:
[Route("api/[controller]")]
[ApiController]
[EnableCors(Global.CORS_ALLOW_ALL_POLICY_NAME)]
public class DealsController : ControllerBase
{
[...]
[HttpGet]
[EnableCors(Global.CORS_ALLOW_ALL_POLICY_NAME)]
public ActionResult<List<Deal>> GetAll()
{
return Store;
}
}
我得到的响应头:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Kestrel
X-Powered-By: ASP.NET
Date: Thu, 06 Sep 2018 12:23:27 GMT
缺少的标题是:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000
答案 0 :(得分:2)
我相信它也可以与LOCALHOST托管一起正常工作,只需执行以下更改并删除以及任何其他更改/配置即可。
替换此:
// Enable CORS (Cross Origin Requests) so that the React app on a different URL can access it
// See https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1
services.AddCors(options =>
{
options.AddPolicy(Global.CORS_ALLOW_ALL_POLICY_NAME, builder => builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials());
});
与此:
services.AddCors();
并替换为:
app.UseCors(Global.CORS_ALLOW_ALL_POLICY_NAME);
与此:
app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
注意:
即使在LOCALHOST上配置了Web Api和React应用也不意味着它们来自同一来源,这是因为它们托管在不同的端口上,例如react app托管在LOCALHOST:3000上,而Web Api是托管在LOCALHOST:5000。如果客户端(反应应用)从其他端口请求,Web api将会投诉。
上面的Web Api代码将允许任何ORIGIN,并且在生产应用程序中这是不安全的,因此您需要允许特定的ORIGIN访问CORS。
答案 1 :(得分:1)
您可以尝试以下类似方法,如此处所述:https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.2
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigin",
builder => builder.WithOrigins("http://example.com"));
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Shows UseCors with named policy.
app.UseCors("AllowSpecificOrigin");
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
在您的情况下,可以将其更改为类似于下面的代码。
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.AddCors(options => options.AddPolicy(Global.CORS_ALLOW_ALL_POLICY_NAME,
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
}));
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors(Global.CORS_ALLOW_ALL_POLICY_NAME);
app.UseHttpsRedirection();
app.UseMvc();
}
}
此代码看上去可能与您的代码没有什么不同,但是,定义动作(您称为构建器)的方式略有不同。希望对您有帮助,祝您好运! :)
答案 2 :(得分:0)
设法通过将用于访问服务器的URL从基于localhost的URL更改为基于IP地址的URL(从localhost / api更改为192.168.1.96/api)来解决该问题。
似乎ATerry提到的部分过滤是基于主机名的:如果主机名是localhost,则IIS不会发送Allow -...标头。问题在于React需要它们。
答案 3 :(得分:0)
我最近也遇到了同样的问题,但是怀疑我的问题是否与CORS有关。因此,我去了将应用程序部署到本地IIS,以检查是否可以解决该问题。然后检查日志,发现与数据模型中的循环引用有关的问题-“检测到属性的自我引用循环。”。在Startup.js中应用了一个操作来解决该问题,
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonOptions(options =>
{
options.SerializerSettings.Formatting = Formatting.Indented;
// this line
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});