带有Windows身份验证的WebAPI CORS - 允许匿名选项请求

Dav*_*one 16 windows-authentication cors asp.net-web-api angularjs

我有一个运行Windows身份验证的WebAPI 2 REST服务.它与网站分开托管,因此我使用ASP.NET CORS NuGet包启用了CORS.我的客户端站点正在使用AngularJS.

到目前为止,这是我经历过的:

  1. 我没有设置withCredentials,因此CORS请求返回401.通过在我的$ httpProvider配置中添加withCredentials解决了这个问题.
  2. 接下来,我使用通配符源设置了EnableCorsAttribute,使用凭据时不允许这样做.通过设置明确的原始列表解决.
  3. 这使我的GET请求成功,但我的POST发出了预检请求,而我没有创建任何控制器操作来支持OPTIONS动词.为了解决这个问题,我将MessageHandler实现为全局OPTIONS处理程序.它只是为任何OPTIONS请求返回200.我知道这不完美,但现在在Fiddler工作.

我被困的地方 - 我的Angular预检电话不包括凭据.根据这个答案,这是设计,因为OPTIONS请求被设计为匿名.但是,Windows身份验证使用401停止请求.

我已经尝试将[AllowAnonymous]属性放在我的MessageHandler上.在我的开发计算机上,它可以工作 - OPTIONS动词不需要身份验证,但其他动词可以.但是,当我构建并部署到测试服务器时,我将继续在我的OPTIONS请求中获得401.

使用Windows身份验证时,是否可以在我的MessageHandler上应用[AllowAnonymous]?如果是的话,有关如何做的任何指导?或者这是一个错误的兔子洞,我应该看一个不同的方法?

更新:我能够通过在IIS中的站点上设置Windows身份验证和匿名身份验证来使其工作.这导致一切都允许匿名,所以我添加了一个全局的Authorize过滤器,同时保留了MessageHandler上的AllowAnonymous.

然而,这感觉就像一个黑客...我一直都明白只应该使用一种身份验证方法(不混合).如果有人有更好的方法,我会很感激听到它.

Igo*_*nko 15

我使用HttpListener进行自托管,以下解决方案为我工作:

  1. 我允许匿名OPTIONS请求
  2. 启用CORS,SupportsCredentials设置为true
var cors = new EnableCorsAttribute("*", "*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
var listener = appBuilder.Properties["System.Net.HttpListener"] as HttpListener;
if (listener != null)
{
    listener.AuthenticationSchemeSelectorDelegate = (request) => {
    if (String.Compare(request.HttpMethod, "OPTIONS", true) == 0)
    {
        return AuthenticationSchemes.Anonymous;
    }
    else
    {
        return AuthenticationSchemes.IntegratedWindowsAuthentication;
    }};
}
Run Code Online (Sandbox Code Playgroud)

  • 如何在webApiConfig.cs注册方法中获取appBuilder实例? (7认同)
  • 这应该被标记为答案,AuthenticationSchemeSelectorDelegate正是您确保OPTIONS请求从任何身份验证设置全局排除所需的.Bravo,这个答案也正是我所需要的.(我建议将'selfhost'标签添加到问题中). (3认同)

Ale*_*xei 8

我一直在努力使CORS请求在以下约束条件下工作(非常类似于OP的):

  • 所有用户的Windows身份验证
  • 不允许匿名身份验证
  • 与IE11一起使用,在某些情况下,它不发送CORS预检请求(或至少不作为OPTIONS请求到达global.asax BeginRequest)

我的最终配置如下:

web.config中 - 允许未经身份验证的(匿名)预检请求(OPTIONS)

<system.web>
    <authentication mode="Windows" />
    <authorization>
        <allow verbs="OPTIONS" users="*"/>
        <deny users="?" />
    </authorization>
</system.web>
Run Code Online (Sandbox Code Playgroud)

的global.asax.cs - 正确回复标题,允许来自其他域的调用者接收数据

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    if (Context.Request.HttpMethod == "OPTIONS")
    {
        if (Context.Request.Headers["Origin"] != null)
            Context.Response.AddHeader("Access-Control-Allow-Origin", Context.Request.Headers["Origin"]);

        Context.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, MaxDataServiceVersion");
        Context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        Context.Response.AddHeader("Access-Control-Allow-Credentials", "true");

        Response.End();
    }
}
Run Code Online (Sandbox Code Playgroud)

CORS启用

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // all requests are enabled in this example. SupportsCredentials must be here to allow authenticated requests          
        var corsAttr = new EnableCorsAttribute("*", "*", "*") { SupportsCredentials = true };
        config.EnableCors(corsAttr);
    }
}

protected void Application_Start()
{
    GlobalConfiguration.Configure(WebApiConfig.Register);
}
Run Code Online (Sandbox Code Playgroud)


jr3*_*jr3 1

戴夫,

在尝试了 CORS 包之后,这就是它对我有用的原因: [EnableCors(origins: " ", headers: " ",methods: "*", SupportsCredentials=true )]

我必须启用 SupportsCredentials=true。Origins、Headers 和Methods 都设置为“*”