使用SessionAuthenticationModule进行CORS预检

时间:2015-03-06 16:46:51

标签: cordova asp.net-web-api cors wif ripple

我真的可以使用这个帮助。简而言之,我试图从本地托管的Cordova应用程序向本地托管的ASP.NET Web API发出跨域(CORS)请求。挑战在于我的客户端应用程序和Web API都使用不同的端口,因此需要CORS支持。我已经尝试了几种不同的方法来规避这一点,但到目前为止还没有运气。以下是具体内容:

  • 我的Cordova应用程序使用VS Tools for Apache Cordova构建,并通过Ripple Emulator在Chrome中运行。这里的挑战是模拟器自动分配端口,我似乎找不到覆盖它的方法。换句话说,如果我可以更改端口以匹配用于我的Web API的端口,那么我可以暂时解决CORS限制。
  • 我的Web API通过对System.Web.Http.Cors和以下启动代码的引用启用了CORS:



public static class WebApiConfig
  {
    public static void Register(HttpConfiguration config)
    {
      var cors = new EnableCorsAttribute("*", "*", "*");  // note: the '*' values are temporary for testing purposes
      config.EnableCors(cors);
    }
  }




  • 我的客户端应用程序正在发出预检请求,因为我的内容类型需要是application / json。尝试将withCredentials标志设置为true无效 - 即在预检请求期间永远不会发送我的承载令牌。

  • 我的Web API通过Windows Identity Foundation受到保护。具体来说,我有一个自定义的SessionAuthenticationModule,它可以验证每个请求,无论它是否与CORS相关。我尝试自定义模块(下面)的成功有限,这样我可以接受预检请求,但我的客户端应用程序的后续POST从未提交过。我应该异步运行这个逻辑吗?



public class CustomSessionAuthenticationModule : SessionAuthenticationModule
  {
    private const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
    private const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
    private const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
    private const string Origin = "Origin";

    protected override void InitializeModule(HttpApplication context)
    {
      base.InitializeModule(context);

      context.BeginRequest += ApplicationOnBeginRequest;
    }

    private static void ApplicationOnBeginRequest(object sender, EventArgs e)
    {
      var application = (HttpApplication)sender;

      if (application.Request.Headers.AllKeys.Contains("Origin") && application.Request.HttpMethod == HttpMethod.Options.ToString())
      {
        application.Response.StatusCode = (int)HttpStatusCode.OK;
        application.Response.Headers.Add(AccessControlAllowOrigin, application.Request.Headers.GetValues(Origin).First());

        string requestedHeaders = string.Join(", ", application.Request.Headers.GetValues(AccessControlRequestHeaders));

        if (!string.IsNullOrEmpty(requestedHeaders))
        {
          application.Response.Headers.Add(AccessControlAllowHeaders, requestedHeaders);
        }
      }
    }
  }




感谢所有您提供的可能有助于解决此问题的建议。

1 个答案:

答案 0 :(得分:0)

为了其他可能遇到类似问题的人的利益,我通过解决方法取得了一些进展。这就是我的所作所为:

  • 在IIS中,在托管我的Web API的同一顶级网站下创建了一个新的虚拟应用程序。这个新的应用程序指向我的Cordova应用程序的源。由于它们都在同一站点和端口下,因此不会发出CORS预检请求。
  • 我还在Chrome中安装了Ripple Emulator,然后点击了工具栏下拉列表中的“启用”按钮,浏览到了我的新网站,并选择了移动网络作为默认平台。

更新2015年12月12日: 缺少的部分是将以下条目添加到web.config中的system.web的授权部分:

<allow verbs="OPTIONS" users="*" />

只要自定义SAM回退到预检请求的基本OnAuthenticateRequest方法,那么一切都能正常工作。