在.NET 4.5中混合Windows和Forms身份验证:如何在创建表单身份验证票证之前保留Request.IsAuthenticated = false?

not*_*ary 7 asp.net authentication iis webforms .net-4.5

更新:

我只用了一些相当简单的修改就解决了这个问题,请参阅下面的自我回答.

原始问题:

我有一个ASP.NET Web应用程序,它使用Windows身份验证和Forms身份验证.Forms身份验证定义为authentication modeWeb.config(参见下面的摘录).在IIS 7中,在Web应用程序(AKA虚拟目录)级别,禁用匿名身份验证,并启用Windows身份验证.

在.NET 1.1到.NET 4.0和IIS6/7后,通过Windows身份验证成功认证/ 7.5,但通过窗体身份验证(创建窗体身份验证票/饼干)认证前,Global.Application_AuthenticateRequest()看到那Request.IsAuthenticated是false.而一旦Request.IsAuthenticated成为true该System.Web.HttpContext.Current.User类型是System.Security.Principal.GenericPrincipal(和User.Identity是System.Web.Security.FormsIdentity)

在IIS7服务器上安装.NET 4.5后,此行为已更改.未对Web.config文件进行任何更改,并且未对IIS手动进行任何更改.我做的唯一改变是安装.NET 4.5.卸载4.5并重新安装4.0后,该行为恢复为"正常".

我注意到的不同行为是,在通过Windows成功进行身份验证之后,但在通过表单进行身份验证之前(尚未创建表单身份验证票证),Application_AuthenticateRequest现在显示的Request.IsAuthenticated是true.此外,System.Web.HttpContext.Current.User.Identity现在System.Security.Principal.WindowsIdentity(而不是FormsIdentity).

  1. 有人可以解释为什么这是不同的?
  2. 是否有可用于强制它以4.0方式工作的配置选项(如web.config更改或IIS设置)?(以便windows auth不会在设置方面胜过表单身份验证Request.IsAuthenticated = true?)

我一直在搜索Msft文档几个小时..他们关于混合Windows和Forms auth的所有信息似乎都已过时(2004-ish),而且.NET 4.5的更改细节在这个特定领域相当稀疏.

摘自web.config :(是的,default.aspx是故意的,在这种情况下我不使用login.aspx,但它已经工作了5年以上,以及所有以前的.net版本).

<authentication mode="Forms">
  <forms name=".ASPXAUTH" protection="All" timeout="200" loginUrl="default.aspx" defaultUrl="~/default.aspx" />
</authentication>
Run Code Online (Sandbox Code Playgroud)

摘自Global.asax.cs:

    protected void Application_AuthenticateRequest(Object sender, EventArgs e)
    {
        if (Request.IsAuthenticated)
        {
            // stuff for authenticated users
            // prior to upgrading to .NET 4.5, this block was not hit until
            // after the forms authentication ticket was created successfully 
            // (after validating user and password against app-specific database)
        }
        else
        {
            // stuff for unauthenticated users
            // prior to upgrading to .NET 4.5, this block was hit
            // AFTER windows auth passed but BEFORE forms auth passed
        }
    }
Run Code Online (Sandbox Code Playgroud)

not*_*ary 2

更新:

我通过实施两阶段身份验证(首先是 Windows 身份验证(如果启用),然后是表单身份验证)并Request.IsAuthenticated完全避免使用来解决了这个问题。

我在项目的一个公共库中创建了一个静态属性:Security.User.IsAuthenticated现在在我之前使用Request.IsAuthenticated. 现在我可以完全控制应用程序中“已验证”的含义。(应该首先这样做;随着时间的推移,我经常发现自己像这样包装现有的 .NET 功能,以便给我更好的控制!)

抱歉,无法透露确切的细节,但基本上它涉及检查当前请求上下文 ( System.Web.HttpContext.Current) 中的一些内容,这些内容是在成功登录后创建表单身份验证票证时设置的(无论是通过 SSO 还是其他方式)。希望这对某人有帮助...

这是我创建的属性。(真正的工作是由 ProprietaryAuthenticationFunction() 完成的,它应该是您的应用程序需要执行的任何操作来验证数据库、LDAP 或其他内容。抱歉,无法与您共享该代码,因为它会违反我的合同条款,但无论如何,大多数企业应用程序应该已经拥有自己专有的身份验证功能。)

        /// <summary>
        /// This only returns true when current request is authenticated via forms 
        /// authentication, meaning the user is logged into the proprietary web app 
        /// (whether by manual login with user/pass or by single sign-on) AND has 
        /// passed whatever authentication method is used by IIS.
        /// </summary>
        public static bool IsAuthenticated
        {
            get
            {
                bool isAuth = 
                    System.Web.HttpContext.Current != null &&
                    System.Web.HttpContext.Current.Request != null &&
                    System.Web.HttpContext.Current.Application != null &&
                    System.Web.HttpContext.Current.Session != null &&
                    System.Web.HttpContext.Current.Request.IsAuthenticated &&
                    ProprietaryAuthenticationFunction(System.Web.HttpContext.Current.Application, System.Web.HttpContext.Current.Session);
                return isAuth;
            }
        }
Run Code Online (Sandbox Code Playgroud)

(请注意,这个特定的网络应用程序大量使用了Session,但如果您不关心,Session您可以省略这些部分。如果您发现任何问题/安全漏洞/性能考虑因素或其他任何问题,请告诉我,谢谢!)