【问题标题】:CORS not working with routeCORS 不适用于路由
【发布时间】: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 来检查是否有问题。

标签: c# asp.net asp.net-web-api cors


【解决方案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
    猜你喜欢
    • 2016-10-15
    • 2013-08-04
    • 2016-02-02
    • 1970-01-01
    • 1970-01-01
    • 2020-10-27
    • 2018-12-31
    • 2016-12-07
    • 2020-10-20
    相关资源
    最近更新 更多