CORS 不适用于路由
Posted
技术标签:
【中文标题】CORS 不适用于路由【英文标题】:CORS not working with route 【发布时间】:2016-10-17 06:37:55 【问题描述】:我的 Web api 上的端点有问题。我有一个 POST 方法不工作,原因是:
对预检请求的响应未通过访问控制检查:否 'Access-Control-Allow-Origin' 标头出现在请求的 资源。因此不允许使用原点“http://localhost:3000” 使用权。响应的 HTTP 状态代码为 405。
我不明白为什么这不起作用,因为我有很多方法确实适用于相同的 COSR 配置。唯一的区别是这个方法有一个指定的路由,如下所示:
// POST: api/Clave
[EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]
[Route("id:int/clave")]
[HttpPost]
public HttpResponseMessage Post(int id, [FromBody]CambioClaveParameters parametros)
UsuarioModel usuario = SQL.GetUsuario(id);
if (Hash.CreateMD5(parametros.ViejaClave) != usuario.Clave.ToUpper())
return Request.CreateResponse(HttpStatusCode.BadRequest);
else if (Hash.CreateMD5(parametros.ViejaClave) == usuario.Clave.ToUpper())
SQL.ModificarClaveUsuario(id, Hash.CreateMD5(parametros.NuevaClave));
return Request.CreateResponse(HttpStatusCode.OK);
else
return Request.CreateResponse(HttpStatusCode.InternalServerError);
关于为什么会发生这种情况的任何想法?
谢谢!
【问题讨论】:
CORS 是否适用于 this 控制器中的其他方法? 我建议您使用prefix.io 来检查是否有问题。 【参考方案1】:根据您消息中的“预检”一词,这是一个 OPTIONS 动词问题。如果您检查请求和响应,我相信您会看到直接在 POST 之前的请求是 OPTIONS 请求。 OPTIONS 请求询问服务器允许调用哪些方法。如果您尚未启用 OPTIONS 响应,或者您的 OPTIONS 响应不包含该 Uri 的 POST 方法,您将收到此响应。
这是描述该概念的链接(请参阅预检 CORS 请求部分) https://msdn.microsoft.com/en-us/magazine/dn532203.aspx
为了解决这种绕过 OPTIONS 设计的所有问题,您可以将与此类似的代码(不要成为***的程序员)添加到新模块或现有模块的 BeginRequest 方法中:
if (context.Request.HttpMethod.ToLower() == "options")
var origin = context.Request.Headers["origin"];
context.Response.StatusCode = 200;
context.Response.AddHeader("Access-Control-Allow-Origin", origin);
context.Response.AddHeader("Access-Control-Allow-Credentials", "true");
context.Response.AddHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");
context.Response.End();
不过,理想情况下,您希望以编程方式确定请求是否有效,如果有效,则输出针对实际允许的内容定制的响应。
【讨论】:
我没有实现 BeginRequest... 我在哪里可以实现它?我正在看一些教程,但不清楚 感谢您让我找到解决此问题的方法...它无法正常工作...但现在错误不同了,我仍然收到 405 响应,但不再来自选项动词 您是否收到相同的消息 - “对预检检查的响应...”?如果是这样,问题继续存在于选项中;如果没有,@Federico 的答案是下一个去处。此外,如果您可以发布浏览器开发工具网络请求的 OPTIONS 和 POST 动词的净化输出以及响应标头,我可能会提供更多帮助。【参考方案2】:希望你做得很好! 您可以使用下面的代码来允许对每个请求响应进行源访问。
protected void Application_BeginRequest(object sender, EventArgs e)
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", *");
如需更多参考,您可以从以下链接获得帮助。 http://enable-cors.org/server_aspnet.html
【讨论】:
【参考方案3】:您的 Web API 响应显然是 405
,这表明您正在调用的 URI 不支持您的 HTTP 方法(在本例中为 POST
)。
从这里开始,您需要了解为什么您的 URI 不支持POST
。最可能的答案是您调用了错误的 URI。您收到 CORS 错误这一事实并不是问题的根源,而是源于您调用的错误 URI 未设置任何 Access-Control-Allow-Origin
标头。
查看您的控制器方法:
[EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]
[Route("id:int/clave")]
[HttpPost]
public HttpResponseMessage Post(int id, [FromBody]CambioClaveParameters parametros)
在我看来,您正在使用 Route
属性,但没有在控制器类中设置 RoutePrefix
属性。
这意味着您的方法的正确 URI 如下:
http://localhost:xxxx/1/clave
而不是,正如您所想的那样:
http://localhost:xxxx/api/Clave/1/clave
如果您想使用第二个 URI 访问您的资源,您需要在控制器中添加一个新的 RoutePrefix
属性:
[RoutePrefix("api/Clave")]
public class ClaveController : ApiController
//..
【讨论】:
我确实已经在控制器上配置了 RoutePrefix 属性......奇怪的是,如果我在本地使用 Postman 测试解决方案,它工作正常。问题在于 AJAX 调用 @NicoRiff 如果您随后使用相关控制器代码(包括 RoutePrefix)更新您的问题,并指定您从 AJAX 调用的 URI。【参考方案4】:如果您使用 web api,只需在根级别创建一个类,将其命名为 Startup.cs 如果您可以尝试在启动时添加以下代码,看看是否有效。此代码将在您的应用程序管道中注入 cors middelware。您可能需要通过 nuget 添加 owin。试试看
[assembly: OwinStartup(typeof(MyProject.API.Startup))]
namespace MyProject.API
public class Startup
public void Configuration(IAppBuilder app)
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(WebApiConfig.Register());
【讨论】:
该类应该在哪里?我应该从哪里调用该函数?。 我没有使用 OWIN以上是关于CORS 不适用于路由的主要内容,如果未能解决你的问题,请参考以下文章
WebAPI - 属性路由 POST 不适用于 WebAPI Cors?
Spring Security 保护路由 hasRole,hasAuthority 不适用于 CORS http 请求
为啥 Laravel 中间件适用于单个路由而不适用于一组路由