我想要做什么
我有一个托管在 Azure 免费计划(源代码:https://github.com/killerrin/Portfolio-Backend)上的后端 ASP.Net Core Web API。
我还有一个客户网站,我想让它使用该 API。客户端应用程序不会托管在 Azure 上,而是托管在 Github Pages 或我有权访问的另一个 Web 托管服务上。因此,域名不会排队。
考虑到这一点,我需要在 Web API 端启用 CORS,但是我已经尝试了几个小时几乎所有的东西,但它拒绝工作。
我如何设置客户端它只是一个用 React.js 编写的简单客户端。我在 Jquery 中通过 AJAX 调用 API。 React 网站可以正常工作,所以我知道不是这样。 Jquery API 调用正如我在尝试 1 中确认的那样工作。这是我进行调用的方式
var apiUrl = "http://andrewgodfroyportfolioapi.azurewebsites.net/api/Authentication";
//alert(username + "|" + password + "|" + apiUrl);
$.ajax({
url: apiUrl,
type: "POST",
data: {
username: username,
password: password
},
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
var authenticatedUser = JSON.parse(response);
//alert("Data Loaded: " + authenticatedUser);
if (onComplete != null) {
onComplete(authenticatedUser);
}
},
error: function (xhr, status, error) {
//alert(xhr.responseText);
if (onComplete != null) {
onComplete(xhr.responseText);
}
}
});
我试过的
尝试 1 - “正确”的方式
https://docs.microsoft.com/en-us/aspnet/core/security/cors
我已按照 Microsoft 网站上的本教程进行操作,尝试了在 Startup.cs 中全局启用它的所有 3 个选项,在每个控制器上设置它并在每个操作上尝试它。
遵循此方法,跨域工作,但仅在单个控制器上的单个操作(POST 到 AccountController)。对于其他所有内容,Microsoft.AspNetCore.Cors
中间件拒绝设置标头。
我通过 NUGET 安装了 Microsoft.AspNetCore.Cors
,版本是 1.1.2
这是我在 Startup.cs 中设置的方法
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add Cors
services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
// Add framework services.
services.AddMvc();
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new CorsAuthorizationFilterFactory("MyPolicy"));
});
...
...
...
}
// This method gets called by the runtime. Use this method to configure
//the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
// Enable Cors
app.UseCors("MyPolicy");
//app.UseMvcWithDefaultRoute();
app.UseMvc();
...
...
...
}
如您所见,我正在按照指示做所有事情。我两次都在 MVC 之前添加了 Cors,当这不起作用时,我尝试将 [EnableCors("MyPolicy")]
放在每个控制器上
[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class AdminController : Controller
尝试 2 - 暴力破解
https://andrewlock.net/adding-default-security-headers-in-asp-net-core/
在尝试了上一次尝试几个小时之后,我想我会尝试通过手动设置标题来强制它,强制它们在每个响应上运行。我在本教程之后执行了此操作,该教程介绍了如何为每个响应手动添加标头。
这些是我添加的标题
.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")
这些是我尝试过的其他标题失败了
.AddCustomHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
.AddCustomHeader("Access-Control-Allow-Headers", "content-type, accept, X-PINGOTHER")
.AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Host, User-Agent, Accept, Accept: application/json, application/json, Accept-Language, Accept-Encoding, Access-Control-Request-Method, Access-Control-Request-Headers, Origin, Connection, Content-Type, Content-Type: application/json, Authorization, Connection, Origin, Referer")
使用这种方法,跨站点标题被正确应用,它们显示在我的开发者控制台和 Postman 中。然而问题是,当它通过 Access-Control-Allow-Origin
检查时,网络浏览器会在(我相信)Access-Control-Allow-Headers
上抛出一个嘶嘶声,声明 415 (Unsupported Media Type)
所以蛮力法也行不通
最后
有没有人让这个工作并且可以伸出援助之手,或者只是能够指出我正确的方向?
编辑
因此,为了让 API 调用通过,我不得不停止使用 JQuery 并切换到纯 Javascript XMLHttpRequest
格式。
尝试 1
我按照 MindingData 的回答设法让 Microsoft.AspNetCore.Cors
工作,除了在 Configure
方法中将 app.UseCors
放在 app.UseMvc
之前。
此外,当与用于通配符支持的 Javascript API 解决方案 options.AllowAnyOrigin()
混合时,它也开始起作用。
尝试 2
所以我设法让尝试 2(蛮力强制它)工作......唯一的例外是 Access-Control-Allow-Origin
的通配符不起作用,因此我必须手动设置有权访问它的域。
它显然不理想,因为我只是希望这个 WebAPI 向所有人广泛开放,但它至少在一个单独的站点上对我有用,这意味着它是一个开始
app.UseSecurityHeadersMiddleware(new SecurityHeadersBuilder()
.AddDefaultSecurePolicy()
.AddCustomHeader("Access-Control-Allow-Origin", "http://localhost:3000")
.AddCustomHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, PATCH, DELETE")
.AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Content-Type, Authorization"));
415 (Unsupported Media Type)
问题,将 Content-Type
请求标头设置为 application/json
。
因为你有一个非常简单的 CORS 策略(允许来自 XXX 域的所有请求),你不需要让它变得如此复杂。首先尝试执行以下操作(CORS 的一个非常基本的实现)。
如果您还没有,请安装 CORS nuget 包。
Install-Package Microsoft.AspNetCore.Cors
在您的 startup.cs 的 ConfigureServices 方法中,添加 CORS 服务。
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(); // Make sure you call this previous to AddMvc
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
然后在您的 startup.cs 的配置方法中,添加以下内容:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Make sure you call this before calling app.UseMvc()
app.UseCors(
options => options.WithOrigins("http://example.com").AllowAnyMethod()
);
app.UseMvc();
}
现在试一试。策略适用于您需要针对不同操作(例如不同主机或不同标头)的不同策略。对于您的简单示例,您确实不需要它。从这个简单的示例开始,然后根据需要进行调整。
进一步阅读:http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/
在 ConfigureServices 添加 services.AddCors();之前 services.AddMvc();
在配置中添加 UseCors app.UseCors(builder => builder .AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader()); app.UseMvc();
要点是在 app.UseMvc()
之前添加 app.UseCors
。
确保在 MVC 之前声明 CORS 功能,以便中间件在 MVC 管道获得控制权并终止请求之前触发。
上述方法生效后,您可以更改它,配置特定的 ORIGIN 以接受 api 调用并避免让您的 API 对任何人开放
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
{
builder.WithOrigins("http://localhost:4200").AllowAnyMethod().AllowAnyHeader();
}));
services.AddMvc();
}
在 configure 方法中告诉 CORS 使用你刚刚创建的策略:
app.UseCors("ApiCorsPolicy");
app.UseMvc();
我刚刚发现这篇关于这个主题的紧凑文章 - https://dzone.com/articles/cors-in-net-core-net-core-security-part-vi
Configure()
相比,ConfigureServices()
中的顺序在这里并不重要
AllowCredentials()
与 AllowAnyOrigin()
一起使用。要使用 AllowCredentials()
,您需要设置 WithOrigins()
。 docs.microsoft.com/en-us/aspnet/core/security/…
我创建了自己的适合我的中间件类,我认为 .net 核心中间件类有问题
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.cs中以这种方式使用它
app.UseCorsMiddleware();
if (!context.Request.Headers.ContainsKey(CorsConstants.Origin)) return this._next(context);
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(builder => builder
.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed((host) => true)
.AllowCredentials()
);
}
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
我为此苦苦挣扎了好几天。
我终于通过将 app.UseCors(CORS_POLICY);
移到 Configure()
的 TOP 来让它工作。
https://weblog.west-wind.com/posts/2016/sep/26/aspnet-core-and-cors-gotchas 确保在 > MVC 之前声明 CORS 功能,因为必须在 MVC 完成之前应用标头要求。 <= 即使我的应用程序没有调用 UseMVC(),将 UseCors() 移到顶部也解决了问题
还:
Microsoft.AspNetCore.Cors 曾经是 .Net Core 2 及更低版本中必需的 NuGet 包;它现在自动成为 .Net Core 3 及更高版本中 Microsoft.AspNetCore 的一部分。
builder.AllowAnyOrigin() 和 .AllowCredentials() CORS 选项现在在 .Net Core 3 及更高版本中是互斥的
CORS 策略似乎要求 Angular 使用 https 调用服务器。无论 .Net Core 服务器的 CORS 配置如何,http URL 似乎都会给出 CORS 错误。例如,http://localhost:52774/api/Contacts 会给出 CORS 错误;只需将 URL 更改为 https://localhost:44333/api/Contacts 即可。
附加说明:
在我的情况下,直到我将 app.UseCors() 移到 app.UseEndpoints(endpoints => endpoints.MapControllers()) 上方,CORS 才会起作用。
在我的情况下,根据 MindingData 的回答,只有 get
请求效果很好。对于其他类型的请求,您需要编写:
app.UseCors(corsPolicyBuilder =>
corsPolicyBuilder.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader()
);
不要忘记添加 .AllowAnyHeader()
对于 .NET 核心 3.1
就我而言,我在添加 cors 中间件之前使用了 https 重定向,并且能够通过更改它们的顺序来解决问题
我的意思是:
改变这个:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseHttpsRedirection();
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
...
}
对此:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseHttpsRedirection();
...
}
顺便说一句,允许来自任何来源和方法的请求对于生产阶段可能不是一个好主意,您应该在生产阶段编写自己的 cors 策略。
为了扩展 user8266077 的 answer,我发现我仍然需要为我的用例在 .NET Core 2.1-preview 中为 preflight requests 提供 OPTIONS 响应:
// https://stackoverflow.com/a/45844400
public class CorsMiddleware
{
private readonly RequestDelegate _next;
public CorsMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
// Added "Accept-Encoding" to this list
context.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Accept-Encoding, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
context.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
// New Code Starts here
if (context.Request.Method == "OPTIONS")
{
context.Response.StatusCode = (int)HttpStatusCode.OK;
await context.Response.WriteAsync(string.Empty);
}
// New Code Ends here
await _next(context);
}
}
然后在 Startup.cs 中启用中间件
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware(typeof(CorsMiddleware));
// ... other middleware inclusion such as ErrorHandling, Caching, etc
app.UseMvc();
}
app.Use<CorsMiddleware>();
await _next(context)
中的任何异常并在发生这种情况时手动设置状态代码和响应来绕过此问题。我还必须向 Access-Control-Allow-Headers 添加“授权”,以便在从需要授权的 react 发出请求时,预检请求才能正常工作。
对于 ASP.NET Core 3.1,这解决了我的问题 https://jasonwatmore.com/post/2020/05/20/aspnet-core-api-allow-cors-requests-from-any-origin-and-with-credentials
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();
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)
{
app.UseRouting();
// global cors policy
app.UseCors(x => x
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowed(origin => true) // allow any origin
.AllowCredentials()); // allow credentials
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(x => x.MapControllers());
}
}
上述过程都没有帮助,然后我阅读了解决问题的 article。
下面是代码。
public void ConfigureServices(IServiceCollection services)
{
// Add service and create Policy with options
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials() );
});
services.AddMvc();
}
和
public void Configure(IApplicationBuilder app)
{
// ...
// global policy - assign here or on each controller
app.UseCors("CorsPolicy");
在我的行动方法之上
[EnableCors("CorsPolicy")]
app.UseCors()
) 和 [EnableCors()]
。您应该使用其中之一 - 但不能同时使用:docs.microsoft.com/en-us/aspnet/core/security/…:Use the [EnableCors] attribute or middleware, not both in the same app.
最简单的解决方案是添加
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors(options => options.AllowAnyOrigin());
app.UseHttpsRedirection();
app.UseMvc();
}
到 Startup.cs。
尝试在 Ajax 调用之前添加 jQuery.support.cors = true;
也可能是您发送到 API 的数据不可靠,
尝试添加以下 JSON 函数
var JSON = JSON || {};
// implement JSON.stringify serialization
JSON.stringify = JSON.stringify || function (obj) {
var t = typeof (obj);
if (t != "object" || obj === null) {
// simple data type
if (t == "string") obj = '"' + obj + '"';
return String(obj);
}
else {
// recurse array or object
var n, v, json = [], arr = (obj && obj.constructor == Array);
for (n in obj) {
v = obj[n]; t = typeof (v);
if (t == "string") v = '"' + v + '"';
else if (t == "object" && v !== null) v = JSON.stringify(v);
json.push((arr ? "" : '"' + n + '":') + String(v));
}
return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
}
};
// implement JSON.parse de-serialization
JSON.parse = JSON.parse || function (str) {
if (str === "") str = '""';
eval("var p=" + str + ";");
return p;
};
然后在您的数据中:对象将其更改为
data: JSON.stringify({
username: username,
password: password
}),
我认为,如果您使用自己的 CORS 中间件,则需要通过检查源标头来确保它确实是 CORS 请求。
public class CorsMiddleware
{
private readonly RequestDelegate _next;
private readonly IMemoryCache _cache;
private readonly ILogger<CorsMiddleware> _logger;
public CorsMiddleware(RequestDelegate next, IMemoryCache cache, ILogger<CorsMiddleware> logger)
{
_next = next;
_cache = cache;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context, IAdministrationApi adminApi)
{
if (context.Request.Headers.ContainsKey(CorsConstants.Origin) || context.Request.Headers.ContainsKey("origin"))
{
if (!context.Request.Headers.TryGetValue(CorsConstants.Origin, out var origin))
{
context.Request.Headers.TryGetValue("origin", out origin);
}
bool isAllowed;
// Getting origin from DB to check with one from request and save it in cache
var result = _cache.GetOrCreateAsync(origin, async cacheEntry => await adminApi.DoesExistAsync(origin));
isAllowed = result.Result.Result;
if (isAllowed)
{
context.Response.Headers.Add(CorsConstants.AccessControlAllowOrigin, origin);
context.Response.Headers.Add(
CorsConstants.AccessControlAllowHeaders,
$"{HeaderNames.Authorization}, {HeaderNames.ContentType}, {HeaderNames.AcceptLanguage}, {HeaderNames.Accept}");
context.Response.Headers.Add(CorsConstants.AccessControlAllowMethods, "POST, GET, PUT, PATCH, DELETE, OPTIONS");
if (context.Request.Method == "OPTIONS")
{
_logger.LogInformation("CORS with origin {Origin} was handled successfully", origin);
context.Response.StatusCode = (int)HttpStatusCode.NoContent;
return;
}
await _next(context);
}
else
{
if (context.Request.Method == "OPTIONS")
{
_logger.LogInformation("Preflight CORS request with origin {Origin} was declined", origin);
context.Response.StatusCode = (int)HttpStatusCode.NoContent;
return;
}
_logger.LogInformation("Simple CORS request with origin {Origin} was declined", origin);
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return;
}
}
await _next(context);
}
Access-Control-Allow-Origin
标头。实际上,我通过没有 Origin
标头的 Postman 发送了请求。这拯救了我的一天! (或者至少我的上午;))
对我来说,这与我使用的代码无关。对于 Azure,我们必须进入应用服务的设置,在侧面菜单中输入“CORS”。在那里我必须添加我从中请求内容的域。一旦我把它放进去,一切都很神奇。
对我来说,解决方案是更正订单:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
对于.Net Core 6
var builder = WebApplication.CreateBuilder(args);
var apiCorsPolicy = "ApiCorsPolicy";
builder.Services.AddCors(options =>
{
options.AddPolicy(name: apiCorsPolicy,
builder =>
{
builder.WithOrigins("http://localhost:4200", "https://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
//.WithMethods("OPTIONS", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseCors(apiCorsPolicy);
app.UseAuthorization();
app.MapControllers();
app.Run();
here 更多示例
在 launchSettings.json 中,在 iisSettings 下,将 anonymousAuthentication 设置为 true:
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:4200/",
"sslPort": 0
}
}
然后,在 Startup.cs 中,在 ConfigureServices 下,在 services.AddMvc 之前,添加:
services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
{
builder
.AllowAnyOrigin()
.WithHeaders(HeaderNames.AccessControlAllowHeaders, "Content-Type")
.AllowAnyMethod()
.AllowCredentials();
}));
然后,在配置方法中,在 app.UseMvc() 之前添加:
app.UseCors("ApiCorsPolicy");
.NET 核心 3.1
为我工作以及文档如何做到这一点:
在启动类中:
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
在 ConfigureServices() 方法中:
services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
在 Configure() 方法中:
app.UseCors(MyAllowSpecificOrigins);
https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1
根据您在 MindingData 的回答中的评论,它与您的 CORS 无关,它工作正常。
您的控制器操作正在返回错误的数据。 HttpCode 415 表示“不支持的媒体类型”。当您将错误的格式传递给控制器(即 XML 到仅接受 json 的控制器)或返回错误的类型(在声明为仅返回 xml 的控制器中返回 Xml)时,就会发生这种情况。
稍后检查您的操作是否存在[Produces("...")]
属性
我正在使用.Net CORE 3.1,当我意识到我的代码已经开始实际工作但我的调试环境被破坏时,我花了很长时间把头撞到墙上,所以如果你想解决这个问题,这里有两个提示问题:
如果您尝试使用 ASP.NET 中间件记录响应标头,则“Access-Control-Allow-Origin”标头将永远不会出现,即使它存在。我不知道如何,但它似乎是在管道之外添加的(最后我不得不使用wireshark来查看它)。 .NET CORE 不会在响应中发送“Access-Control-Allow-Origin”,除非您的请求中有“Origin”标头。 Postman 不会自动设置,因此您需要自己添加。
这是我的代码:)
app.Use((ctx, next) =>
{
ctx.Response.Headers.Add("Access-Control-Allow-Origin", ctx.Request.Headers["Origin"]);
ctx.Response.Headers.Add("Access-Control-Allow-Methods", "*");
ctx.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
ctx.Response.Headers.Add("Access-Control-Allow-Headers", "AccessToken,Content-Type");
ctx.Response.Headers.Add("Access-Control-Expose-Headers", "*");
if (ctx.Request.Method.ToLower() == "options")
{
ctx.Response.StatusCode = 204;
return Task.CompletedTask;
}
return next();
});
就我而言,我在 UserRouting 之前使用 UseCors 进行了修复。
这是使用顶级语句配置 CORS 的 Program.cs 文件的 .NET 6 示例。可以看出,builder.Services.AddCors 和 app.UseCors 是必需的语句。两个注释的 UseCors 语句也有效,并被包括在内以显示其他选项。我没有对我的 ASP.NET API 控制器进行任何更改。
作为参考,我的开发 Angular 应用程序在 localhost:4200 上运行,并使用 https://localhost:7262 连接到开发 ASP.NET API 服务器。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCors();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
//app.UseCors(options => options.WithOrigins("http://localhost:4200").AllowAnyMethod());
//app.UseCors(options => options.WithOrigins("http://localhost:4200").WithMethods(new string[] {"POST", "PUT"}));
app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod());
app.MapControllers();
app.Run();
简单易行的方法。
安装包
Install-Package Microsoft.AspNetCore.Cors
将下面的代码放在 startup.cs 文件中
app.UseCors(options => options.AllowAnyOrigin());
使用自定义操作/控制器属性来设置 CORS 标头。
例子:
public class AllowMyRequestsAttribute : ControllerAttribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
// check origin
var origin = context.HttpContext.Request.Headers["origin"].FirstOrDefault();
if (origin == someValidOrigin)
{
context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", origin);
context.HttpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
context.HttpContext.Response.Headers.Add("Access-Control-Allow-Headers", "*");
context.HttpContext.Response.Headers.Add("Access-Control-Allow-Methods", "*");
// Add whatever CORS Headers you need.
}
}
public void OnActionExecuting(ActionExecutingContext context)
{
// empty
}
}
然后在 Web API 控制器/操作上:
[ApiController]
[AllowMyRequests]
public class MyController : ApiController
{
[HttpGet]
public ActionResult<string> Get()
{
return "Hello World";
}
}
在我的情况下,我的原始名称末尾的字符 /
导致了一个问题。
在 .NET Core 3.1 中为我解决的解决方案:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(c => c.AddPolicy("PolicyName", policy => {
policy.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader();
}));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors("PolicyName");
}
在 ASP.NET Core 3.1 中对我有用的解决方案:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
services.AddControllersWithViews();
}
然后更改以下内容:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors("CorsPolicy");
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
然后程序运行并解决了错误。
我在上面得到了 MindingData 的答案,但我必须使用 Microsoft.AspNet.Cors 而不是 Microsoft.AspNetCore.Cors。我在 Visual Studio 2019 中使用 .NetCore Web 应用程序 API 项目
这
Microsoft.AspNetCore.Cors
将允许您使用内置功能执行 CORS,但它不处理 OPTIONS 请求。到目前为止,最好的解决方法是按照上一篇文章中的建议创建一个新的中间件。检查以下帖子中标记为正确的答案:
Enable OPTIONS header for CORS on .NET Core Web API
这是我如何做到的。
我看到在某些答案中,他们设置了 app.UserCors("xxxPloicy")
并将 [EnableCors("xxxPloicy")]
放入控制器中。您不需要两者都做。
以下是步骤。
在 Startup.cs 里面的 ConfigureServices 添加以下代码。
services.AddCors(c=>c.AddPolicy("xxxPolicy",builder => {
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
如果要在整个项目中应用,请在 Startup.cs 的 Configure 方法中添加以下代码
app.UseCors("xxxPolicy");
或者
如果要将其添加到特定控制器,请添加启用 cors 代码,如下所示。
[EnableCors("xxxPolicy")]
[Route("api/[controller]")]
[ApiController]
public class TutorialController : ControllerBase {}
欲了解更多信息:see this
不定期副业成功案例分享
app.UseCors
AFTER ``app.UseMvc()` 时,这不太可能起作用。中间件按照注册的顺序执行options.DisableHttpsRequirement();
才能使所有这些工作。似乎 https cors 设置不适用。