如何在 ASP.net Core WebAPI 中启用 CORS
How to enable CORS in ASP.net Core WebAPI
我想做什么
我有一个后端 ASP.Net Core Web API 托管在 Azure 免费计划(源代码:https://github.com/killerrin/Portfolio-Backend)上。
我还有一个客户网站,我想使用它 API。客户端应用程序不会托管在 Azure 上,而是托管在 Github 页面或我有权访问的另一个 Web 托管服务上。因此,域名不会排队。
考虑到这一点,我需要在 Web API 端启用 CORS,但是我已经尝试了几个小时的几乎所有方法,但它拒绝工作。
我如何进行客户端设置
它只是一个用 React.js 编写的简单客户端。我在 Jquery 中通过 AJAX 调用 APIs。 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 - 'proper' 方式
https://docs.microsoft.com/en-us/aspnet/core/security/cors
我已经按照 Microsoft 网站上的这个教程进行了 T,尝试了在 Startup.cs 中全局启用它的所有 3 个选项,在每个控制器上设置它并在每个操作上尝试它。
按照此方法,跨域工作,但仅在单个控制器(POST 到 AccountController)上的单个操作上起作用。对于其他所有内容,Microsoft.AspNetCore.Cors
中间件拒绝设置 headers.
我通过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/
在尝试上次尝试几个小时后,我想我会尝试通过尝试手动设置 headers 来暴力破解它,迫使它们在每次响应时都为 运行。我按照本教程执行此操作,了解如何手动将 headers 添加到每个响应。
这些是我添加的headers
.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")
这些是其他的headers我试过但失败了
.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")
通过这种方法,Cross Site headers 得到了正确应用,它们出现在我的开发人员控制台和 Postman 中。然而,问题是当它通过 Access-Control-Allow-Origin
检查时,网络浏览器会发出嘶嘶声(我相信) Access-Control-Allow-Headers
说明 415 (Unsupported Media Type)
所以暴力破解也不行
终于
有没有人让这个工作,可以伸出援手,或者只是能够指出我正确的方向?
编辑
所以为了让 API 呼叫通过,我不得不停止使用 JQuery 并切换到纯 Javascript XMLHttpRequest
格式。
尝试 1
除了在 Configure
方法中将 app.UseCors
放在 app.UseMvc
之前,我按照 MindingData 的回答设法让 Microsoft.AspNetCore.Cors
工作。
此外,当与 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"));
因为你有一个非常简单的 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 的 Configure 方法中添加以下内容:
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();
}
现在开始吧。策略适用于您希望针对不同操作(例如不同主机或不同 headers)使用不同策略的情况。对于您的简单示例,您真的不需要它。从这个简单的示例开始,然后根据需要进行调整。
进一步阅读:http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/
根据您在 MindingData 的回答中的评论,它与您的 CORS 无关,它工作正常。
您的控制器操作return输入了错误的数据。 HttpCode 415 表示 "Unsupported Media type"。当您将错误的格式传递给控制器(即 XML 给只接受 json 的控制器)或者当您 return 错误的类型(return Xml 在声明为仅 return xml).
的控制器中
稍后检查您的操作是否存在[Produces("...")]
属性
尝试在 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
}),
在 ConfigureServices 中添加 services.AddCors();
BEFORE 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();
}
在配置方法中告诉 CORS 使用您刚刚创建的策略:
app.UseCors("ApiCorsPolicy");
app.UseMvc();
我刚找到这篇关于这个主题的紧凑文章 -
https://dzone.com/articles/cors-in-net-core-net-core-security-part-vi
我创建了自己的适用于我的中间件 class,我认为 .net 核心中间件有问题 class
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();
在我的例子中,根据 MindingData 的回答,只有 get
请求运行良好。对于其他类型的请求,您需要写:
app.UseCors(corsPolicyBuilder =>
corsPolicyBuilder.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader()
);
别忘了加上.AllowAnyHeader()
在我的用例的 .NET Core 2.1 预览版中扩展 user8266077's , I found that I still needed to supply OPTIONS response for preflight requests:
//
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();
}
None 上述程序有帮助,然后我阅读 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");
并且在我的 actionmethod 之上
[EnableCors("CorsPolicy")]
我认为如果您使用自己的 CORS 中间件,您需要通过检查 [=13= 来确保它确实是 CORS 请求]来源header。
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);
}
对我来说,这与我使用的代码无关。对于 Azure,我们必须进入 App Service 的设置,在侧面菜单中输入 "CORS"。在那里我必须添加我从中请求内容的域。一旦我有了它,一切都变得神奇了。
我在上面找到了 MindingData 的答案,但我不得不使用 Microsoft.AspNet.Cors 而不是 Microsoft.AspNetCore.Cors。我在 Visual Studio 2019
中使用 .NetCore Web 应用程序 API 项目
最简单的解决方案是添加
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。
在 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");
我为此苦苦挣扎了 DAYS。
我终于通过将 app.UseCors(CORS_POLICY);
移动到 Configure()
的 TOP 来让它工作。
https://weblog.west-wind.com/posts/2016/sep/26/aspnet-core-and-cors-gotchas
Make sure you declare the CORS functionality before > MVC as the
headers have to be applied before MVC completes the request.
<= Even though my app didn't call UseMVC()
, moving UseCors()
to the top fixed the problem
还有:
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
即可。
补充说明:
In my case, CORS wouldn't work until I moved app.UseCors()
above app.UseEndpoints(endpoints => endpoints.MapControllers())
.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(builder => builder
.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed((host) => true)
.AllowCredentials()
);
}
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
.NET 核心 3.1
为我工作以及文档说如何做:
在启动中 class:
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
Microsoft.AspNetCore.Cors
将允许您使用内置功能执行 CORS,但它不处理 OPTIONS 请求。
迄今为止最好的解决方法是按照之前 post 中的建议创建一个新的中间件。检查以下标记为正确的答案 post:
简单易行的方法。
- 安装包
Install-Package Microsoft.AspNetCore.Cors
- 将下面的代码放入 startup.cs 文件
app.UseCors(options => options.AllowAnyOrigin());
我正在使用 .Net CORE 3.1,当我意识到我的代码已经开始实际工作但我的调试环境被破坏时,我花了很长时间用这个来撞墙,所以这里有 2 个提示,如果你'正在尝试解决问题:
如果您尝试使用 ASP.NET 中间件记录响应 header,"Access-Control-Allow-Origin" header 将永远不会出现,即使它是那里。不知道怎么弄的,好像是加在pipeline外的(最后不得不用wireshark才看到)
.NET CORE 不会在响应中发送 "Access-Control-Allow-Origin",除非您的请求中包含 "Origin" header。 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..
这是我的做法。
我看到在某些答案中,他们正在设置 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
使用自定义 Action/Controller 属性设置 CORS headers。
示例:
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";
}
}
如果您使用的是 app.UseHttpsRedirection()
,并且您使用的不是 SSL 端口,请考虑在此处添加答案。
我使用 blazor webassembly 作为客户端,asp.net web api 核心作为后端,也有 cors 问题。
我用这些代码找到了解决方案:
我的 ASP.Net 核心网站 api Startup.cs ConfigureServices 和 Configure 方法的第一行如下所示:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
{
builder.WithOrigins("http://example.com").AllowAnyMethod().AllowAnyHeader();
}));
//other code below...
}
和我的配置方法:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(
options => options.WithOrigins("http://example.com").AllowAnyMethod().AllowAnyHeader()
);
//other code below...
}
将 http://example.com
更改为您的客户端域或 IP 地址
在我的案例中,原始名称末尾的字符 /
导致了问题。
在 .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?}");
});
}
然后程序运行并解决了错误。
对于 .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 策略。
for 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());
}
}
对我来说,当我明确设置了我要发送的 header 后,它就开始工作了。我正在添加 content-type header,然后它起作用了。
.net
.WithHeaders("Authorization","Content-Type")
javascript:
this.fetchoptions = {
method: 'GET',
cache: 'no-cache',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
redirect: 'follow',
};
AspNetCoreModuleV2 无法处理导致预检问题的选项
我发现 .net 核心模块不能很好地处理 OPTIONS,这造成了一个大的 CORS 问题:
解决方法:去掉星号*
在 web.config 中,从模块中排除 OPTIONS verb 因为 IIS 已经处理了这个动词 OPTIONSVerbHandler:
<add name="aspNetCore" path="*" verb="* modules="AspNetCoreModuleV2" resourceType="Unspecified" />
用这个
<add name="aspNetCore" path="*" verb="GET,POST,PUT,DELETE" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
对我来说,解决办法是更正订单:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
这是一个 Program.cs 文件的 .NET 6 示例,它使用 top-level 语句来配置 CORS。可以看出,builder.Services.AddCors 和 app.UseCors 是必需的语句。两个带注释的 UseCors 语句也有效,并包含在内以显示其他选项。我没有对 ASP.NET API 控制器进行任何更改。
作为参考,我的开发 Angular 应用程序在 localhost:4200 上 运行 并且正在使用 https:// 连接到开发 ASP.NET API 服务器本地主机:7262.
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();
.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 更多示例
我想做什么
我有一个后端 ASP.Net Core Web API 托管在 Azure 免费计划(源代码:https://github.com/killerrin/Portfolio-Backend)上。
我还有一个客户网站,我想使用它 API。客户端应用程序不会托管在 Azure 上,而是托管在 Github 页面或我有权访问的另一个 Web 托管服务上。因此,域名不会排队。
考虑到这一点,我需要在 Web API 端启用 CORS,但是我已经尝试了几个小时的几乎所有方法,但它拒绝工作。
我如何进行客户端设置 它只是一个用 React.js 编写的简单客户端。我在 Jquery 中通过 AJAX 调用 APIs。 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 - 'proper' 方式
https://docs.microsoft.com/en-us/aspnet/core/security/cors
我已经按照 Microsoft 网站上的这个教程进行了 T,尝试了在 Startup.cs 中全局启用它的所有 3 个选项,在每个控制器上设置它并在每个操作上尝试它。
按照此方法,跨域工作,但仅在单个控制器(POST 到 AccountController)上的单个操作上起作用。对于其他所有内容,Microsoft.AspNetCore.Cors
中间件拒绝设置 headers.
我通过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/
在尝试上次尝试几个小时后,我想我会尝试通过尝试手动设置 headers 来暴力破解它,迫使它们在每次响应时都为 运行。我按照本教程执行此操作,了解如何手动将 headers 添加到每个响应。
这些是我添加的headers
.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")
这些是其他的headers我试过但失败了
.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")
通过这种方法,Cross Site headers 得到了正确应用,它们出现在我的开发人员控制台和 Postman 中。然而,问题是当它通过 Access-Control-Allow-Origin
检查时,网络浏览器会发出嘶嘶声(我相信) Access-Control-Allow-Headers
说明 415 (Unsupported Media Type)
所以暴力破解也不行
终于
有没有人让这个工作,可以伸出援手,或者只是能够指出我正确的方向?
编辑
所以为了让 API 呼叫通过,我不得不停止使用 JQuery 并切换到纯 Javascript XMLHttpRequest
格式。
尝试 1
除了在 Configure
方法中将 app.UseCors
放在 app.UseMvc
之前,我按照 MindingData 的回答设法让 Microsoft.AspNetCore.Cors
工作。
此外,当与 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"));
因为你有一个非常简单的 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 的 Configure 方法中添加以下内容:
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();
}
现在开始吧。策略适用于您希望针对不同操作(例如不同主机或不同 headers)使用不同策略的情况。对于您的简单示例,您真的不需要它。从这个简单的示例开始,然后根据需要进行调整。
进一步阅读:http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/
根据您在 MindingData 的回答中的评论,它与您的 CORS 无关,它工作正常。
您的控制器操作return输入了错误的数据。 HttpCode 415 表示 "Unsupported Media type"。当您将错误的格式传递给控制器(即 XML 给只接受 json 的控制器)或者当您 return 错误的类型(return Xml 在声明为仅 return xml).
的控制器中稍后检查您的操作是否存在[Produces("...")]
属性
尝试在 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
}),
在 ConfigureServices 中添加
services.AddCors();
BEFORE 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();
}
在配置方法中告诉 CORS 使用您刚刚创建的策略:
app.UseCors("ApiCorsPolicy");
app.UseMvc();
我刚找到这篇关于这个主题的紧凑文章 - https://dzone.com/articles/cors-in-net-core-net-core-security-part-vi
我创建了自己的适用于我的中间件 class,我认为 .net 核心中间件有问题 class
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();
在我的例子中,根据 MindingData 的回答,只有 get
请求运行良好。对于其他类型的请求,您需要写:
app.UseCors(corsPolicyBuilder =>
corsPolicyBuilder.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader()
);
别忘了加上.AllowAnyHeader()
在我的用例的 .NET Core 2.1 预览版中扩展 user8266077's
//
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();
}
None 上述程序有帮助,然后我阅读 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");
并且在我的 actionmethod 之上
[EnableCors("CorsPolicy")]
我认为如果您使用自己的 CORS 中间件,您需要通过检查 [=13= 来确保它确实是 CORS 请求]来源header。
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);
}
对我来说,这与我使用的代码无关。对于 Azure,我们必须进入 App Service 的设置,在侧面菜单中输入 "CORS"。在那里我必须添加我从中请求内容的域。一旦我有了它,一切都变得神奇了。
我在上面找到了 MindingData 的答案,但我不得不使用 Microsoft.AspNet.Cors 而不是 Microsoft.AspNetCore.Cors。我在 Visual Studio 2019
中使用 .NetCore Web 应用程序 API 项目最简单的解决方案是添加
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。
在 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");
我为此苦苦挣扎了 DAYS。
我终于通过将 app.UseCors(CORS_POLICY);
移动到 Configure()
的 TOP 来让它工作。
https://weblog.west-wind.com/posts/2016/sep/26/aspnet-core-and-cors-gotchas
Make sure you declare the CORS functionality before > MVC as the headers have to be applied before MVC completes the request.
<= Even though my app didn't call
UseMVC()
, movingUseCors()
to the top fixed the problem
还有:
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
即可。
补充说明:
In my case, CORS wouldn't work until I moved
app.UseCors()
aboveapp.UseEndpoints(endpoints => endpoints.MapControllers())
.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(builder => builder
.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed((host) => true)
.AllowCredentials()
);
}
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
.NET 核心 3.1
为我工作以及文档说如何做:
在启动中 class:
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
Microsoft.AspNetCore.Cors
将允许您使用内置功能执行 CORS,但它不处理 OPTIONS 请求。 迄今为止最好的解决方法是按照之前 post 中的建议创建一个新的中间件。检查以下标记为正确的答案 post:
简单易行的方法。
- 安装包
Install-Package Microsoft.AspNetCore.Cors
- 将下面的代码放入 startup.cs 文件
app.UseCors(options => options.AllowAnyOrigin());
我正在使用 .Net CORE 3.1,当我意识到我的代码已经开始实际工作但我的调试环境被破坏时,我花了很长时间用这个来撞墙,所以这里有 2 个提示,如果你'正在尝试解决问题:
如果您尝试使用 ASP.NET 中间件记录响应 header,"Access-Control-Allow-Origin" header 将永远不会出现,即使它是那里。不知道怎么弄的,好像是加在pipeline外的(最后不得不用wireshark才看到)
.NET CORE 不会在响应中发送 "Access-Control-Allow-Origin",除非您的请求中包含 "Origin" header。 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..
这是我的做法。
我看到在某些答案中,他们正在设置 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
使用自定义 Action/Controller 属性设置 CORS headers。
示例:
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";
}
}
如果您使用的是 app.UseHttpsRedirection()
,并且您使用的不是 SSL 端口,请考虑在此处添加答案。
我使用 blazor webassembly 作为客户端,asp.net web api 核心作为后端,也有 cors 问题。
我用这些代码找到了解决方案:
我的 ASP.Net 核心网站 api Startup.cs ConfigureServices 和 Configure 方法的第一行如下所示:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
{
builder.WithOrigins("http://example.com").AllowAnyMethod().AllowAnyHeader();
}));
//other code below...
}
和我的配置方法:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(
options => options.WithOrigins("http://example.com").AllowAnyMethod().AllowAnyHeader()
);
//other code below...
}
将 http://example.com
更改为您的客户端域或 IP 地址
在我的案例中,原始名称末尾的字符 /
导致了问题。
在 .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?}");
});
}
然后程序运行并解决了错误。
对于 .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 策略。
for 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());
}
}
对我来说,当我明确设置了我要发送的 header 后,它就开始工作了。我正在添加 content-type header,然后它起作用了。
.net
.WithHeaders("Authorization","Content-Type")
javascript:
this.fetchoptions = {
method: 'GET',
cache: 'no-cache',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
redirect: 'follow',
};
AspNetCoreModuleV2 无法处理导致预检问题的选项
我发现 .net 核心模块不能很好地处理 OPTIONS,这造成了一个大的 CORS 问题:
解决方法:去掉星号*
在 web.config 中,从模块中排除 OPTIONS verb 因为 IIS 已经处理了这个动词 OPTIONSVerbHandler:
<add name="aspNetCore" path="*" verb="* modules="AspNetCoreModuleV2" resourceType="Unspecified" />
用这个
<add name="aspNetCore" path="*" verb="GET,POST,PUT,DELETE" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
对我来说,解决办法是更正订单:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
这是一个 Program.cs 文件的 .NET 6 示例,它使用 top-level 语句来配置 CORS。可以看出,builder.Services.AddCors 和 app.UseCors 是必需的语句。两个带注释的 UseCors 语句也有效,并包含在内以显示其他选项。我没有对 ASP.NET API 控制器进行任何更改。
作为参考,我的开发 Angular 应用程序在 localhost:4200 上 运行 并且正在使用 https:// 连接到开发 ASP.NET API 服务器本地主机:7262.
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();
.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 更多示例