kil*_*rin 148 c# rest cross-domain cors asp.net-core
我想做什么
我有一个Azure免费计划托管的后端ASP.Net核心Web API(源代码:https://github.com/killerrin/Portfolio-Backend).
我还有一个客户网站,我想要消费该API.客户端应用程序不会托管在Azure上,而是托管在Github Pages或我可以访问的其他Web托管服务上.因此,域名不会排队.
考虑到这一点,我需要在Web API端启用CORS,但是我现在已经尝试了好几个小时并拒绝工作.
我如何设置客户端 它只是一个用React.js编写的简单客户端.我在Jquery中通过AJAX调用API.React网站有效,所以我知道不是这样.Jquery API调用正如我在Attempt 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);
}
}
});
Run Code Online (Sandbox Code Playgroud)
我试过了什么
尝试1 - "正确"的方式
https://docs.microsoft.com/en-us/aspnet/core/security/cors
我已经在微软网站上关注了这个教程,尝试了在Startup.cs中全局启用它的所有3个选项,在每个控制器上设置它并在每个Action上尝试它.
遵循此方法,Cross Domain可以工作,但只能在单个控制器上的一个Action上运行(POST到AccountController).对于其他一切,Microsoft.AspNetCore.Cors中间件拒绝设置标头.
我Microsoft.AspNetCore.Cors通过NUGET 安装,版本是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();
...
...
...
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我正在做所有事情.我在MVC之前添加了Cors两次,当这不起作用时,我试图[EnableCors("MyPolicy")]像每个控制器一样
[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class AdminController : Controller
Run Code Online (Sandbox Code Playgroud)
尝试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")
Run Code Online (Sandbox Code Playgroud)
这些是我试过的其他标题失败了
.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")
Run Code Online (Sandbox Code Playgroud)
使用此方法,正确应用了跨站点标头,它们显示在我的开发人员控制台和邮递员中.然而问题是,当它通过Access-Control-Allow-Origin检查时,webbrowser抛出了一个(我相信)Access-Control-Allow-Headers陈述的嘶嘶声415 (Unsupported Media Type)
所以蛮力方法也不起作用
最后
有没有人得到这个工作,可以伸出援助之手,或者只是能指出我正确的方向?
编辑
因此,为了让API调用完成,我不得不停止使用JQuery并切换到纯Javascript XMLHttpRequest格式.
尝试1
我设法Microsoft.AspNetCore.Cors通过遵循MindingData的答案来完成工作,除了在之前的Configure方法中.app.UseCorsapp.UseMvc
此外,当与Javascript API解决方案混合使用时options.AllowAnyOrigin(),通配符支持也开始起作用.
尝试2
所以我设法让Attempt 2(暴力强迫它)工作......唯一的例外是Wildcard for 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"));
Run Code Online (Sandbox Code Playgroud)
Min*_*ata 193
因为您有一个非常简单的CORS策略(允许来自XXX域的所有请求),所以您不需要使它变得如此复杂.首先尝试执行以下操作(CORS的一个非常基本的实现).
如果您还没有,请安装CORS nuget包.
Install-Package Microsoft.AspNetCore.Cors
Run Code Online (Sandbox Code Playgroud)
在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);
}
Run Code Online (Sandbox Code Playgroud)
然后在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();
}
Run Code Online (Sandbox Code Playgroud)
现在开始吧.策略适用于您需要针对不同操作的不同策略(例如,不同的主机或不同的标头).对于您的简单示例,您真的不需要它.从这个简单的例子开始,然后根据需要进行调整.
进一步阅读:http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/
小智 175
services.AddCors(); BEFORE services.AddMvc();在Configure中添加UseCors
app.UseCors(builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
app.UseMvc();
Run Code Online (Sandbox Code Playgroud)重点是app.UseCors之前添加app.UseMvc().
确保在MVC之前声明CORS功能,以便在MVC管道获得控制权并终止请求之前触发中间件.
Mo *_*sis 27
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(builder => builder
.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed((host) => true)
.AllowCredentials()
);
}
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
Run Code Online (Sandbox Code Playgroud)
小智 23
我创建了自己的中间件类,对我有用,我认为.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>();
}
}
Run Code Online (Sandbox Code Playgroud)
并在startup.cs中以这种方式使用它
app.UseCorsMiddleware();
Run Code Online (Sandbox Code Playgroud)
Fog*_*Day 20
我为此苦苦挣扎了几天。
我终于通过移动它得到工作app.UseCors(CORS_POLICY);的TOP的Configure()。
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 及更高版本中互斥https. 无论 .Net Core 服务器的 CORS 配置如何,http URL 似乎都会给出 CORS 错误。例如,http://localhost:52774/api/Contacts会给出 CORS 错误;只需更改 URL 即可https://localhost:44333/api/Contacts工作。附加说明:
就我而言,CORS 在我移动
app.UseCors()到app.UseEndpoints(endpoints => endpoints.MapControllers()).
Leo*_*doX 16
对于.Net 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();
Run Code Online (Sandbox Code Playgroud)
这里有更多例子
Tow*_*hid 14
在我的情况下,get根据MindingData的答案,只有请求才能正常工作.对于其他类型的请求,您需要编写:
app.UseCors(corsPolicyBuilder =>
corsPolicyBuilder.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader()
);
Run Code Online (Sandbox Code Playgroud)
别忘了添加 .AllowAnyHeader()
小智 12
就我而言,我在添加cors 中间件之前使用了https 重定向,并且能够通过更改它们的顺序来解决问题
我的意思是:
改变这个:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseHttpsRedirection();
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
...
}
Run Code Online (Sandbox Code Playgroud)
对此:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseHttpsRedirection();
...
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,允许来自任何来源和方法的请求在生产阶段可能不是一个好主意,您应该在生产阶段编写自己的 cors 策略。
小智 8
为了扩展user8266077的答案,我发现在我的用例中,我仍然需要为.NET Core 2.1预览中的预检请求提供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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在Startup.cs中启用类似的中间件
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware(typeof(CorsMiddleware));
// ... other middleware inclusion such as ErrorHandling, Caching, etc
app.UseMvc();
}
Run Code Online (Sandbox Code Playgroud)
以上过程均无济于事,然后我阅读解决了此问题的文章。
下面是代码。
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();
}
Run Code Online (Sandbox Code Playgroud)
和
public void Configure(IApplicationBuilder app)
{
// ...
// global policy - assign here or on each controller
app.UseCors("CorsPolicy");
Run Code Online (Sandbox Code Playgroud)
在我的行动方法之上
[EnableCors("CorsPolicy")]
Run Code Online (Sandbox Code Playgroud)
最简单的解决方案是添加
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors(options => options.AllowAnyOrigin());
app.UseHttpsRedirection();
app.UseMvc();
}
Run Code Online (Sandbox Code Playgroud)
到 Startup.cs。
对于 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());
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
对我来说,解决方案是纠正顺序:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Run Code Online (Sandbox Code Playgroud)
小智 5
以下是使用顶级语句配置 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();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
140934 次 |
| 最近记录: |