启用Windows身份验证的IIS中的CORS请求的401响应

时间:2012-05-23 15:25:16

标签: iis-7.5 windows-authentication asp.net-web-api ntlm cors

我正在尝试在我的WebAPI项目中启用CORS支持,如果我启用匿名身份验证,那么一切正常,但是使用Windows Auth +禁用匿名身份验证,发送的OPTIONS请求始终返回401未经授权的响应。请求它的站点位于DOMAIN上,因此应该可以进行呼叫,有没有办法解决问题而不禁用Windows身份验证?

13 个答案:

答案 0 :(得分:37)

您只能为匿名用户提供OPTIONS谓词。

<system.web>
  <authentication mode="Windows" />
    <authorization>
      <allow verbs="OPTIONS" users="*"/>
      <deny users="?" />
  </authorization>
</system.web>

根据W3C规范,浏览器会从CORS预检中排除用户凭据:https://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html#preflight-request

答案 1 :(得分:22)

几年后,但是通过@dariusriggins和@ lex-li的回答,我设法将以下代码添加到我的Global.asax中:

    var uri = 'data:text/xml,' + encodeURIComponent({your xml});

    var link = document.createElement("a");
    link.href = uri;


    link.style = "visibility:hidden";
    link.download = fileName + ".xml";

    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

httpOrigin实际上是在允许的主机列表中查找的,但这只是复杂的事情。这意味着所有其他请求都经过验证,但选项只会返回。

感谢您提出这个问题,如果没有它我就会迷失方向!

答案 2 :(得分:14)

来自MS:

如果禁用匿名身份验证,则设计IIS会向任何请求返回401。如果他们已启用Windows身份验证,那么在这种情况下401响应将具有WWW-Authenticate标头以允许客户端启动身份验证握手。然后问题是客户使用的客户端是否可以进行Windows身份验证。

最后,似乎可能存在一个潜在的问题,即是否可以配置URL以允许一个动词(在本例中为OPTIONS)允许匿名访问,但需要对其他动词进行Windows身份验证。 IIS不支持通过简单配置。通过启用匿名和Windows身份验证,在拒绝访问匿名用户的内容上设置ACL,然后为相关URL配置处理程序映射以便它不验证是否存在,可能会出现此行为与URL关联的文件。但需要花一些时间来证实这一点。

答案 3 :(得分:4)

解决此问题的最简单方法是使用条件request_method = ^ OPTIONS $创建重写规则。然后将操作设置为自定义响应,将其设置为200 OK。然后所有选项请求将以200而不是401响应。这将解决CORS问题。

当然,您仍需要确保拥有正确的跨源请求标头。

当启用集成身份验证时,这将停止响应401的选项请求(没有任何凭据)。

答案 4 :(得分:4)

接受的答案是正确的,但我正在使用“带有iisnode和npm cors模块的节点”安装一段时间来对其他api进行故障排除,并且对于为所有用户启用匿名身份验证感到不舒服。由于它是一个节点应用程序,因此system.web标记没有做太多工作。我最终添加了以下web.config:

<system.webServer>
<security>
  <requestFiltering>
    <hiddenSegments>
      <add segment="node_modules" />
    </hiddenSegments>
  </requestFiltering>
  <authorization>
    <add accessType="Allow" verbs="OPTIONS" users="?" />
    <add accessType="Deny" verbs="GET, PUT, POST, DELETE" users="?" />
  </authorization>
</security>
</system.webServer>

答案 5 :(得分:3)

由于IE 10 and 11中的错误,我今天遇到了同样的问题,我正在使用ServiceStack而不是WebApi,但这种方法也适用于你。

  1. 在IIS网站上启用Windows集成和匿名身份验证。
  2. 在ServiceStack管道上有一系列过滤器,
    • 为了处理Cors和OPTIONS请求,在On Options请求中,我添加了必要的标题并结束请求,
    • 过滤器检查包含HttpRequest是否经过身份验证?,
    • etc filter,
  3. 在通过所有过滤器后,它会执行服务。

    CorsFeature.cs

    AuthenticateFilter

    在我的AppHost中,

    appHost.Plugins.Add(new CorsFeature());
    
    appHost.RequestFilters.Add(AuthenticateFilter.Authenticate);
    

    我已修改CorsFeature以处理OptionsRequest,除了添加标题,验证过滤器以检查已验证的请求!

答案 6 :(得分:2)

Related Question: IIS hijacks CORS Preflight OPTIONS request

从多个位置找到的答案中合并信息。如果您需要在Intranet上使用Windows身份验证在ASP.net页面方法上启用CORS,这似乎是可行的。如果不对web.config进行更改,则无法使用。

您需要将此添加到Global.asax

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        string httpOrigin = HttpContext.Current.Request.Params["HTTP_ORIGIN"] ?? HttpContext.Current.Request.Params["ORIGIN"] ?? "*";
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");

        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        {
            HttpContext.Current.Response.StatusCode = 200;
            var httpApplication = sender as HttpApplication;
            httpApplication.CompleteRequest();
        }
    }

这是web.config

 <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." 
           verb="*" type="System.Web.Handlers.TransferRequestHandler" 
           preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>

答案 7 :(得分:1)

我正在使用Web API和OWIN,我尝试了所有建议的解决方案,但唯一有效的是以下

//use it in your startup class
app.Use((context, next) =>
{
    if (context.Request.Headers.Any(k => k.Key.Contains("Origin")) && context.Request.Method == "OPTIONS")
    {
        context.Response.StatusCode = 200;
        context.Response.Headers.Add("Access-Control-Allow-Origin", new string[1] { "ALLOWED_ORIGIN" });
        context.Response.Headers.Add("Access-Control-Allow-Headers", new string[4] { "Origin", "X-Requested-With", "Content-Type", "Accept" });
        context.Response.Headers.Add("Access-Control-Allow-Methods", new string[5] { "GET", "POST", "PUT", "DELETE", "OPTIONS" });
        context.Response.Headers.Add("Access-Control-Allow-Credentials", new string[1] { "true" });

        return context.Response.WriteAsync("");
    }

    return next.Invoke();
});

//this is important! Without it, it didn't work (probably because the middleware was too late)
app.UseStageMarker(PipelineStage.Authenticate);

您需要在一个OWIN启动类中的某处插入此代码。 调用app.UseStageMarker(PipelineStage.Authenticate)非常重要,否则预检检查失败。 UseStageMarker的更多信息 - &gt; https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline

您需要明确定义允许的标头也很重要。如果您使用*作为占位符,则会失败。

也许对某人有帮助。

答案 8 :(得分:1)

我知道这是一个古老的问题,有几个可能的解决方案(以及更多问题),但是如果其他人遇到此问题,IIS CORS 1.0将于17年11月推出:

https://blogs.iis.net/iisteam/introducing-iis-cors-1-0

https://docs.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference

您可以通过IIS Windows平台安装程序(WPI)下载它。这样可以解决您的许多CORS身份验证问题。享受吧!

答案 9 :(得分:1)

扩展@dariusriggins提供的答案。检查这篇文章:Microsoft | Developer: Putting it all together – CORS tutorial

对于IIS配置:

授权规则

Authorization rule

授权阶段(或授权事件),我们需要确保仅允许来自CORS预检的匿名请求,并要求所有其他传入请求都提供身份验证凭据。我们可以通过授权规则来实现。默认情况下,授予所有用户访问该站点的权限的授权规则已经存在,并且由IIS默认提供。我们将从修改此规则开始,以仅允许匿名用户发送使用OPTIONS http动词的请求。以下是IIS中此授权规则的目标配置:

编辑授权规则

Edit Authorization rule

答案 10 :(得分:0)

对我有用(使用AngularJS或JQuery时)是在客户端上添加withCredentials:true:

$http.get("http://localhost:88/api/tests", {withCredentials :true})

在服务器上启用CORS,这是通过nuget的Microsoft.Owin.Cors完成的,并将其添加到Startup中,如下所示:

public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();

        ConfigureOAuth(app);

        WebApiConfig.Register(config);
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(config);

    }

参考文献:

答案 11 :(得分:0)

此 IIS 扩展 (IIS CORS Module) 帮助我解决了对启用了 Windows 身份验证的 IIS 托管应用程序的 401-未经授权的预检请求。安装此模块后,我执行了 IISRESET,并在我的 Web 应用程序的 Web.config 文件中添加了以下内容:

<configuration>
    <configSections>
        <!-- ... (configSections must be the first element!) -->
    </configSections>
    <system.webServer>
        <cors enabled="true">
            <add origin="http://localhost:3000" allowCredentials="true" maxAge="120">
                <allowHeaders allowAllRequestedHeaders="true"/>
                <!-- Added 'allowMethods' just in case. -->
                <allowMethods>
                    <add method="HEAD"/>
                    <add method="GET"/>
                    <add method="POST"/>
                    <add method="PUT"/>
                    <add method="DELETE"/>
                    <add method="OPTIONS"/>
                </allowMethods>
            </add>
        </cors>
    </system.webServer>
</configuration>

您可以在此处找到有关如何配置 IIS CORS 模块的更多信息: Getting started with the IIS CORS Module

答案 12 :(得分:-1)

在WebApiConfig.cs中启用EnableCorsAttribute上的SupportCredentials为我做了诀窍:

public static void Register(HttpConfiguration config)
{        
    //enable cors request just from localhost:15136 
    var cors = new EnableCorsAttribute("http://localhost:15136", "*", "*");
    cors.SupportsCredentials = true;
    config.EnableCors(cors);

    //other stuff
}

https://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

确保从javascript({withCredentials :true}

调用时发送凭据