如何设置Thread.CurrentPrincipal以在整个应用程序中使用?

时间:2009-08-31 08:32:42

标签: asp.net authentication identity principal

在ASP.net应用程序中,我正在使用我编写的自定义成员资格提供程序的Login控件。我想要做的是在用户通过身份验证后立即将Thread.CurrentPrincipal设置为我的自定义Principal对象。

我正在使用setter:Thread.CurrentPrincipal并且它为我设置了Principal对象,但是在所有后续线程中,这个CurrentPrincipal被默认值覆盖。

以下是我对Login控件的Authenticate事件的代码:

protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
    {
        string username = Login1.UserName;
        string password = Login1.Password;

        if (Membership.ValidateUser(username, password))
        {
            var login = sender as Login;
            var phoenixIdentity = new PhoenixIdentity("B", "Forms" , true);
            var principal = new PhoenixPrincipal(phoenixIdentity);

            Thread.CurrentPrincipal = principal;
            AppDomain.CurrentDomain.SetThreadPrincipal(principal);

            HttpContext.Current.User = principal;

            e.Authenticated = true;
        }
    }

例如,假设我使用用户名A登录,一切顺利...验证通过,但我使用Identity对象中的用户名B对用户进行硬编码,该对象设置为我设置为{{的Principal对象1}}对象。

当我在此方法结束时检查哪个用户设置为CurrentPrincipal标识时,它表示它是用户B.但是当我加载另一个页面然后检查CurrentPrincipal的标识是什么时,它说它是用户A.

那么,如何让我的CurrentPrincipal对象在所有其他线程中保持持久性,以及此Login控件在何时/何时设置线程的CurrentPrincipal对象?

3 个答案:

答案 0 :(得分:2)

Tadas没错,FormsAuthentication正确实现不会导致此问题。

即使没有登录,您的页面也可以访问,只有在登录页面中,您的线程原则是由您手动设置的,但当您点击其他URL时,它肯定不会调用您的登录页面并记住每个页面都运行在不同的页面上线。如果您请求第一页并设置线程原则并且您在同一浏览器实例中请求第二页,则它可能是也可能不是完全相同的线程。

这就是FormsAuthentication的工作方式,

  1. 检查是否设置了Auth Cookie,然后将用户引导至登录页面
  2. 登录页面必须验证并设置auth cookie,例如FormsAuthentication.SetAuthCookie
  3. 在每次访问页面之前,执行第1步。
  4. 成功验证Auth Cookie后,ASP.NET会根据您的成员资格组件在内部设置当前用户和所有不同的参数。
  5. ASP.NET Global.asax文件可以为您提供一些事件,您可以在其中插入代码以在验证成功后立即检查您可以更改当前用户,记住在登录页面上设置您当前的原则将无济于事
  6. 当我们使用会话来存储某些重要信息时,我们遇到了类似的问题,在没有重建auth会话之后,所以我们编写了一个HTTP模块,在它的init方法中,我们附加了AfterRequestAcquired事件,在这种情况下你可以编写你的用于实例化所有重要用户相关变量的代码。

答案 1 :(得分:1)

您可以处理FormsAuthentication_OnAuthenticate(对象发件人,FormsAuthenticationEventArgs e)(在Global.asax中)并在此处设置CurrentPrincipal。


void FormsAuthentication_OnAuthenticate(object sender, FormsAuthenticationEventArgs e)
{
var phoenixIdentity = new PhoenixIdentity("B", "Forms" , true);
var principal = new PhoenixPrincipal(phoenixIdentity);
e.User = principal;
}

答案 2 :(得分:1)

这就是我在FormsAuthentication_OnAuthenticate方法中所做的:

if (FormsAuthentication.CookiesSupported)
        {
            if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
            {
                try
                {
                    FormsAuthenticationTicket ticket = 
                        FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value);

                    var myIdentity = new GenericIdentity("B");
                    var principal = new GenericPrincipal(myIdentity, new string[]{"rola1"});
                    e.User = principal;
                }
                catch (Exception ex)
                {
                    // Decrypt method failed.
                }
            }
        }
        else
        {
            throw new HttpException("Cookieless Forms Authentication is not " +
                                    "supported for this application.");
        }

似乎它正在运行它应该做的......只是如果我把我的自定义主体/身份对作为e.User,那么我有序列化问题,我需要接下来解决...谢谢你们。 ..