在 .NET Core Web API 上为 CORS 启用选项 header
Enable OPTIONS header for CORS on .NET Core Web API
我在 Whosebug 上找不到解决方案后解决了这个问题,所以我在这里分享我的问题和答案中的解决方案。
使用 AddCors 在我的 .NET Core Web Api 应用程序中启用跨域策略后,它仍然无法在浏览器中运行。这是因为包括 Chrome 和 Firefox 在内的浏览器将首先发送一个 OPTIONS 请求,而我的应用程序仅响应 204 No Content.
将中间件 class 添加到您的项目以处理 OPTIONS 动词。
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Hosting;
namespace Web.Middlewares
{
public class OptionsMiddleware
{
private readonly RequestDelegate _next;
public OptionsMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext context)
{
return BeginInvoke(context);
}
private Task BeginInvoke(HttpContext context)
{
if (context.Request.Method == "OPTIONS")
{
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)context.Request.Headers["Origin"] });
context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });
context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
context.Response.StatusCode = 200;
return context.Response.WriteAsync("OK");
}
return _next.Invoke(context);
}
}
public static class OptionsMiddlewareExtensions
{
public static IApplicationBuilder UseOptions(this IApplicationBuilder builder)
{
return builder.UseMiddleware<OptionsMiddleware>();
}
}
}
然后在 Configure 方法的 Startup.cs 中添加 app.UseOptions();
作为第一行。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseOptions();
}
我知道已经回答了。只是用更新的信息回答。所以它会帮助别人。
它现在内置于 ASP.NET 核心框架中。
关注https://docs.microsoft.com/en-us/aspnet/core/security/cors
并替换
app.UseCors(builder =>
builder.WithOrigins("http://example.com"));
与
app.UseCors(builder =>
builder.WithOrigins("http://example.com")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials());
这对我有用:
确保:
app.UseCors(builder => {
builder.AllowAnyOrigin();
builder.AllowAnyMethod();
builder.AllowAnyHeader();
});
发生在任何这些之前:
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseCookiePolicy();
记住,我们正在处理 "pipeline"。 cors 的东西必须放在第一位。
-金扎尼
我想在单个方法上允许这样做,而不是使用中间件在任何方法上允许这样做。这就是我最后做的事情:
'OPTIONS' 方法的手动处理
[HttpOptions("/find")]
public IActionResult FindOptions()
{
Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)Request.Headers["Origin"] });
Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST, OPTIONS" }); // new[] { "GET, POST, PUT, DELETE, OPTIONS" }
Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
return NoContent();
}
[HttpPost("/find")]
public async Task<IActionResult> FindOptions([FromForm]Find_POSTModel model)
{
AllowCrossOrigin();
// your code...
}
private void AllowCrossOrigin()
{
Uri origin = null;
Uri.TryCreate(Request.Headers["Origin"].FirstOrDefault(), UriKind.Absolute, out origin);
if (origin != null && IsOriginAllowed(origin))
Response.Headers.Add("Access-Control-Allow-Origin", $"{origin.Scheme}://{origin.Host}");
}
当然,您可以根据需要实施IsOriginAllowed
private bool IsOriginAllowed(Uri origin)
{
const string myDomain = "mydomain.com";
const string[] allowedDomains = new []{ "example.com", "sub.example.com" };
return
allowedDomains.Contains(origin.Host)
|| origin.Host.EndsWith($".{myDomain}");
}
您可以在 how to enable CORS for POST requests on a single endpoint
上找到更多详细信息
不需要额外的中间件。正如上面已经提到的,唯一需要的是 Cors 配置中允许的 OPTIONS 方法。
您可以按照此处的建议使用 AllowAnyMethod:https://whosebug.com/a/55764660/11921910
但是只允许这样的特定内容更安全:
app.UseCors(builder => builder
.WithOrigins("https://localhost", "https://production.company.com") /* list of environments that will access this api */
.WithMethods("GET", "OPTIONS") /* assuming your endpoint only supports GET */
.WithHeaders("Origin", "Authorization") /* headers apart of safe-list ones that you use */
);
有些 headers 总是允许的:
https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_request_header
我想针对我在本地测试 api 和客户端 Web 应用程序的具体情况给出具体答案。我知道这是一个迟到的条目,但 CORS 在 dot net 核心中发生了很大变化,我想,像我这样的新手可能会受益于完整的 post。
对我来说,这是两个背靠背发生的问题。
- CORS 拒绝错误
- 还有 Firefox 上的 OPTIONS 问题(我假设 chrome 会做同样的事情)
- 我的 API 也是 运行 HTTPS
- 网络应用没有 HTTPS
- 他们都运行在本地,为清楚起见再次提及这一点。
首先,这会转到 public void ConfigureServices(IServiceCollection services)
//lets add some CORS stuff
services.AddCors(options =>
{
options.AddDefaultPolicy(builder => {
builder.WithOrigins("http://localhost:3000",
"http://www.contoso.com");
builder.AllowAnyMethod();
builder.AllowAnyHeader();
builder.AllowCredentials();
});
});
然后,这个,转到,public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseCors();
欢迎。
[HttpOptions("/find")]
public IActionResult FindOptions()
{
Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)Request.Headers["Origin"] });
Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST, OPTIONS" }); // new[] { "GET, POST, PUT, DELETE, OPTIONS" }
Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
return NoContent();
}`enter code here`
AspNetCoreModuleV2 OPTIONS问题
.Net 核心模块不知道如何处理导致预检 CORS 问题的 OPTIONS,因此解决方案是排除 OPTIONS 动词由它处理。这是通过将 * 替换为您想要的动词(选项除外)来完成的。不用担心,OPTIONS 动词将由默认加载的 OPTIONSHandler 处理:
IIS
解决方法:修改web.config
<add name="aspNetCore" path="*" verb="* modules="AspNetCoreModuleV2" resourceType="Unspecified" />
像这样:
<add name="aspNetCore" path="*" verb="GET,POST,PUT,DELETE" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
IIS Express:对于 Visual Studio 调试器
我尝试修改 .vs\ProjectName\config\applicationhost.config
在文件的底部,但没有希望。因此,在这种特定情况下,您可以使用所选答案。
实际上,none 个答案对我有用,但我终于弄清楚了问题所在,我不敢相信
我刚搬家 app.UserCors("PolicyName");
app.UseAuthorization();
之前
它开始工作了!
我认为这可能对某人有帮助。
services.AddCors(options =>
{
options.AddPolicy("EnableCORS", bl =>
{
bl.WithOrigins(origins)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.Build();
});
});
..........................
app.UseAuthentication();
app.UseCors("EnableCORS");
.....
app.UseAuthorization();
我在 Whosebug 上找不到解决方案后解决了这个问题,所以我在这里分享我的问题和答案中的解决方案。
使用 AddCors 在我的 .NET Core Web Api 应用程序中启用跨域策略后,它仍然无法在浏览器中运行。这是因为包括 Chrome 和 Firefox 在内的浏览器将首先发送一个 OPTIONS 请求,而我的应用程序仅响应 204 No Content.
将中间件 class 添加到您的项目以处理 OPTIONS 动词。
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Hosting;
namespace Web.Middlewares
{
public class OptionsMiddleware
{
private readonly RequestDelegate _next;
public OptionsMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext context)
{
return BeginInvoke(context);
}
private Task BeginInvoke(HttpContext context)
{
if (context.Request.Method == "OPTIONS")
{
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)context.Request.Headers["Origin"] });
context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });
context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
context.Response.StatusCode = 200;
return context.Response.WriteAsync("OK");
}
return _next.Invoke(context);
}
}
public static class OptionsMiddlewareExtensions
{
public static IApplicationBuilder UseOptions(this IApplicationBuilder builder)
{
return builder.UseMiddleware<OptionsMiddleware>();
}
}
}
然后在 Configure 方法的 Startup.cs 中添加 app.UseOptions();
作为第一行。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseOptions();
}
我知道已经回答了。只是用更新的信息回答。所以它会帮助别人。
它现在内置于 ASP.NET 核心框架中。
关注https://docs.microsoft.com/en-us/aspnet/core/security/cors
并替换
app.UseCors(builder =>
builder.WithOrigins("http://example.com"));
与
app.UseCors(builder =>
builder.WithOrigins("http://example.com")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials());
这对我有用:
确保:
app.UseCors(builder => {
builder.AllowAnyOrigin();
builder.AllowAnyMethod();
builder.AllowAnyHeader();
});
发生在任何这些之前:
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseCookiePolicy();
记住,我们正在处理 "pipeline"。 cors 的东西必须放在第一位。
-金扎尼
我想在单个方法上允许这样做,而不是使用中间件在任何方法上允许这样做。这就是我最后做的事情:
'OPTIONS' 方法的手动处理
[HttpOptions("/find")]
public IActionResult FindOptions()
{
Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)Request.Headers["Origin"] });
Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST, OPTIONS" }); // new[] { "GET, POST, PUT, DELETE, OPTIONS" }
Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
return NoContent();
}
[HttpPost("/find")]
public async Task<IActionResult> FindOptions([FromForm]Find_POSTModel model)
{
AllowCrossOrigin();
// your code...
}
private void AllowCrossOrigin()
{
Uri origin = null;
Uri.TryCreate(Request.Headers["Origin"].FirstOrDefault(), UriKind.Absolute, out origin);
if (origin != null && IsOriginAllowed(origin))
Response.Headers.Add("Access-Control-Allow-Origin", $"{origin.Scheme}://{origin.Host}");
}
当然,您可以根据需要实施IsOriginAllowed
private bool IsOriginAllowed(Uri origin)
{
const string myDomain = "mydomain.com";
const string[] allowedDomains = new []{ "example.com", "sub.example.com" };
return
allowedDomains.Contains(origin.Host)
|| origin.Host.EndsWith($".{myDomain}");
}
您可以在 how to enable CORS for POST requests on a single endpoint
上找到更多详细信息不需要额外的中间件。正如上面已经提到的,唯一需要的是 Cors 配置中允许的 OPTIONS 方法。 您可以按照此处的建议使用 AllowAnyMethod:https://whosebug.com/a/55764660/11921910
但是只允许这样的特定内容更安全:
app.UseCors(builder => builder
.WithOrigins("https://localhost", "https://production.company.com") /* list of environments that will access this api */
.WithMethods("GET", "OPTIONS") /* assuming your endpoint only supports GET */
.WithHeaders("Origin", "Authorization") /* headers apart of safe-list ones that you use */
);
有些 headers 总是允许的: https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_request_header
我想针对我在本地测试 api 和客户端 Web 应用程序的具体情况给出具体答案。我知道这是一个迟到的条目,但 CORS 在 dot net 核心中发生了很大变化,我想,像我这样的新手可能会受益于完整的 post。
对我来说,这是两个背靠背发生的问题。
- CORS 拒绝错误
- 还有 Firefox 上的 OPTIONS 问题(我假设 chrome 会做同样的事情)
- 我的 API 也是 运行 HTTPS
- 网络应用没有 HTTPS
- 他们都运行在本地,为清楚起见再次提及这一点。
首先,这会转到 public void ConfigureServices(IServiceCollection services)
//lets add some CORS stuff
services.AddCors(options =>
{
options.AddDefaultPolicy(builder => {
builder.WithOrigins("http://localhost:3000",
"http://www.contoso.com");
builder.AllowAnyMethod();
builder.AllowAnyHeader();
builder.AllowCredentials();
});
});
然后,这个,转到,public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseCors();
欢迎。
[HttpOptions("/find")] public IActionResult FindOptions()
{
Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)Request.Headers["Origin"] });
Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST, OPTIONS" }); // new[] { "GET, POST, PUT, DELETE, OPTIONS" }
Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
return NoContent();
}`enter code here`
AspNetCoreModuleV2 OPTIONS问题
.Net 核心模块不知道如何处理导致预检 CORS 问题的 OPTIONS,因此解决方案是排除 OPTIONS 动词由它处理。这是通过将 * 替换为您想要的动词(选项除外)来完成的。不用担心,OPTIONS 动词将由默认加载的 OPTIONSHandler 处理:
IIS
解决方法:修改web.config
<add name="aspNetCore" path="*" verb="* modules="AspNetCoreModuleV2" resourceType="Unspecified" />
像这样:
<add name="aspNetCore" path="*" verb="GET,POST,PUT,DELETE" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
IIS Express:对于 Visual Studio 调试器
我尝试修改 .vs\ProjectName\config\applicationhost.config
在文件的底部,但没有希望。因此,在这种特定情况下,您可以使用所选答案。
实际上,none 个答案对我有用,但我终于弄清楚了问题所在,我不敢相信
我刚搬家 app.UserCors("PolicyName");
app.UseAuthorization();
之前
它开始工作了!
我认为这可能对某人有帮助。
services.AddCors(options =>
{
options.AddPolicy("EnableCORS", bl =>
{
bl.WithOrigins(origins)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.Build();
});
});
..........................
app.UseAuthentication();
app.UseCors("EnableCORS");
.....
app.UseAuthorization();