2

我有一个站点,我们在其中设置了带有 Windows 身份验证的自动登录,如果失败,它会要求用户名/密码以表单形式登录。

这样做的方式是,我们将授权设置为带有特定页面(Winlogin.aspx)的表单。Winlogin.aspx 是使用授权 Windows 设置的。在 Winlogin.aspx.cs 的代码中,它获取 this.Request.ServerVariables["LOGON_USER"] 并使用 request.GetUserToken() 使用用户的令牌创建 FormsAuthenticationTicket,设置具有加密版本的 cookie 并将浏览器发送到表单授权的 login.aspx 页面。

Login.aspx 获取 cookie,对其进行解密,并假设将 HttpContext.Current.User 设置为在授权成功后从 Winlog.aspx 发送的用户创建的 WindowsIdentity。

这已经在 IIS6 上完美运行了一年多,但我们正在更新我们的服务器并迁移到 IIS 7,但现在我得到了一个无效的模拟令牌 - 它不能被复制。

这是使用的代码

// Extract the roles from the cookie, and assign to our current principal, which is attached to the HttpContext.
FormsAuthenticationTicket winAuthTicket = FormsAuthentication.Decrypt(authCookie.Value);
String token = winAuthTicket.UserData;
IntPtr userToken = new IntPtr(int.Parse(token);

-----> Line that gives error now. <-----
WindowsIdentity identity = new WindowsIdentity(userToken, "NTLM", WindowsAccountType.Normal, true); 

HttpContext.Current.User = new WindowsPrincipal(identity);

我已经研究了 2 天,试图弄清楚。

有人有想法吗?

4

2 回答 2

1

要解决此问题,您必须使用WindowsIdentity不重复的令牌。所以你必须传递HttpContext.User一个由原始令牌(不重复)生成的WindowsPrinciple传递一个。WindowsIdentity我一直在想办法绕过这个问题,但看起来唯一的方法是在LogonUser每次需要WindowsIdentity.

您无法重复使用原始令牌,因为HttpContext.User在每次请求之后都会被释放(出于安全原因)。

于 2014-07-23T20:26:31.420 回答
0

我认为问题是,您不能在另一个请求中重用相同的 WindowsPrincipal 实例,因为可能包含分配给 WindowsPrincipal 的一些引用的 SafeHandle 实例已与上一个请求一起处理,而且您不能复制 WindowsIdentity.Token -它必须重新生成。您必须克隆 WindowsIdentity - 这将摆脱引用依赖项。然后,您可以通过 WindowsIdentity.Token 或其他方式重新生成网站身份验证令牌。

我有同样的问题,我已经通过这种方式解决了。

var user = new WindowsPrincipal(((WindowsIdentity)HttpContext.Current.User.Identity).Clone());
//now assign the user again to the current context's user or do some other stuff like storing the clone to session for future requests...
于 2019-02-14T13:06:25.473 回答