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

更新:

我通过一些相当简单的更改解决了这个问题,请参阅下面的自我回答.

原始问题:

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

在通过Windows身份验证成功进行身份验证后,但在通过Forms身份验证(创建表单身份验证票证/ cookie)进行身份验证之前,在.NET 1.1到.NET 4.0和IIS6 / 7 / 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).

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

我一直在搜索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>

摘自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
        }
    }

解决方法

回复:有人可以解释一下为什么会有所不同吗?

我注意到System.Web.Hosting.IIS7WorkerRequest.SynchronizeVariables()的更改是在4.5中进行的.差异如下所示(源代码来自反射器):

在4.0中,如果启用了Windows身份验证,则SynchronizeVariables()仅同步IPrincipal / IHttpUser.

internal void SynchronizeVariables(HttpContext context)
{
    ...
    if (context.IsChangeInUserPrincipal && WindowsAuthenticationModule.IsEnabled) 
    // the second condition checks if authentication.Mode == AuthenticationMode.Windows
    {
        context.SetPrincipalNoDemand(this.GetUserPrincipal(),false);
    }
    ...
}

在4.5中,如果启用了任何身份验证,SynchronizeVariables()会同步IPrincipal / IHttpUser(AuthenticationConfig.Mode!= AuthenticationMode.None)

[PermissionSet(SecurityAction.Assert,Unrestricted=true)]
internal void SynchronizeVariables(HttpContext context)
{
    ...
    if (context.IsChangeInUserPrincipal && IsAuthenticationEnabled)
    {
        context.SetPrincipalNoDemand(this.GetUserPrincipal(),false);
    }
    ...
}

private static bool IsAuthenticationEnabled
{
    get
    {
        if (!s_AuthenticationChecked)
        {
            bool flag = AuthenticationConfig.Mode != AuthenticationMode.None;
            s_AuthenticationEnabled = flag;
            s_AuthenticationChecked = true;
        }
        return s_AuthenticationEnabled;
    }
}

我怀疑上述更改是身份验证中行为更改的根本原因.

在更改之前:ASP.NET不与IIS同步以获取用户的Windows身份(虽然IIS确实使Windows认证).由于未进行身份验证,ASP.NET仍可以执行表单身份验证.

更改后:ASP.NET与IIS同步以获取用户的Windows标识.因为设置了context.Current.User,所以ASP.NET不会进行表单身份验证.

相关文章

### 创建一个gRPC服务项目(grpc服务端)和一个 webapi项目(...
一、SiganlR 使用的协议类型 1.websocket即时通讯协议 2.Ser...
.Net 6 WebApi 项目 在Linux系统上 打包成Docker镜像,发布为...
一、 PD简介PowerDesigner 是一个集所有现代建模技术于一身的...
一、存储过程 存储过程就像数据库中运行的方法(函数) 优点:...
一、Ueditor的下载 1、百度编辑器下载地址:http://ueditor....