angular - 跨域请求被阻止——使用 Angular 和 ASP.NET Core 构建的应用程序
问题描述
我正在使用 Angular 和 ASP.NET Core 构建一个网站。
在某些页面上,我想从 Web API 获取数据。当我运行应用程序时,浏览器 (Firefox) 显示
跨域请求被阻止:同源策略不允许读取位于 ...(url)的远程资源(原因:CORS 预检通道的 CORS 标头“Access-Control-Allow-Headers”中缺少令牌“授权”)。
我尝试了其他浏览器,得到了同样的错误。
出于授权考虑,我使用 aHttpInterceptor
为来自 Angular 前端的每个请求插入授权标头。
然后我查看了我的 ASP.NET Core 后端。我将 CORS 策略设置为app.UseCors(builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); });
,但它仍然不起作用。
我用 Postman 测试了 API,它工作正常。
哪里出了问题?
该Startup.cs
文件。
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.AddMvc().AddJsonOptions(
opt => opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
services.AddEntityFrameworkSqlServer();
services.AddCors();
services.AddSignalR();
services.AddDbContext<ApplicationDbContext>(opt =>
{
opt.UseSqlServer(Configuration.GetConnectionString("Remote"));
});
services.AddIdentity<ApplicationUser, IdentityRole>(opts =>
{
opts.Password.RequireDigit = true;
opts.Password.RequireLowercase = true;
opts.Password.RequireUppercase = true;
opts.Password.RequireNonAlphanumeric = false;
opts.Password.RequiredLength = 7;
}).AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthentication(opts =>
{
opts.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(cfg =>
{
cfg.RequireHttpsMetadata = false;
cfg.TokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = Configuration["Auth:Jwt:Issuer"],
ValidAudience = Configuration["Auth:Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Auth:Jwt:Key"])),
ClockSkew = TimeSpan.Zero,
RequireExpirationTime = true,
ValidateIssuerSigningKey = true,
ValidateAudience = true
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("NonUser", policy => policy.RequireRole("RestrauntOwner", "RestrauntAdmin", "SystemAdmin"));
});
}
// 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.UseExceptionHandler("/Home/Error");
}
app.UseCors(builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); });
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
app.UseSignalR(route =>
{
route.MapHub<OrderHub>("/orderhub");
});
app.UseCookiePolicy();
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
}
有点奇怪。我在我的 Windows PC 上开发这个已经有一段时间了。我在我的 MacBook 上克隆了这个项目,它在 macOS 上运行良好,没有任何问题。
解决方案
如果你不能完全让它工作,这里有几个提示:
您的来源必须与浏览器发送的内容完全匹配。
如果是HTTP就必须放HTTP,HTTPS必须是HTTPS。
端口号也必须包括在内并且正确。
"http://localhost:5001"
因此,如果您使用上述设置,请不要设置CORS 规则,因为这不是同一个 URL!查看浏览器或 Fiddler 以确保它完全正确,并确保它符合您的期望。如果在 HTTP 和 HTTPS 之间切换,很容易混淆。
如果您发送的内容不匹配,您将收到带有空响应的 204
- 如果您弄错了,它不会向您透露它所期望的正确数据
标题不区分大小写
- 如果你愿意,你可以放
"authorization"
or"Authorization"
或。"aUtHoRiZaTiOn"
您必须包括方法和标头
- 如果您没有指定允许的 HTTP 方法使用
WithMethods
,否则AllowAnyMethod
它将不起作用。这很容易被忽略——尤其是对于一个 GET 请求。
如果使用中间件或分支 MVC 管道,您可以在该级别添加 CORS。
对于app.UseSpa
(如果您使用 Microsoft 的 SPA 托管机制),您可以这样做
app.UseSpa(spa =>
{
// see https://go.microsoft.com/fwlink/?linkid=864501
// CORS just for the SPA
spa.ApplicationBuilder.UseCors(builder =>
{
// Must specify Methods
builder.WithMethods("GET");
// Case insensitive headers
builder.WithHeaders("AuthoriZatioN");
// Can supply a list or one by one, either is fine
builder.WithOrigins("http://localhost:5000");
builder.WithOrigins("https://localhost:5001");
});
提琴手很有用
Fiddler 将向您展示 CORS 成功所需的条件。这是authorization
标题和GET
方法。
您可以R
在更改服务器配置后点击先前的请求以重新运行它。这样您就不必一直启动浏览器。
请务必查看Headers
响应部分,因为即使成功,实际内容也是 0 字节。
推荐阅读
- audio - AudiManager 从蓝牙更改为 EAR_PIECE 不起作用
- java - 使用 Spring Rest 将 ID 转换为类类型
- javascript - $ 未定义(出于某种奇怪的原因)
- php - 我得到值 date1 和 date2 但只显示 0 值
- mysql - mysql - 如何在具有不同定义的列上拥有外键
- java - 如何调用和显示
- javascript - 带有子项的 Material UI 菜单不会关闭整个菜单
- css - 渐变背景溢出边框
- unity3d - 我可以在 Unity 中制作一款适用于所有 PC VR 设备(Oculus、HTC VIVE)的 VR 游戏吗
- javascript - 如何访问动态对象键