2009-08-31 134 views
5

在ASP.net应用我使用的是,我写了一个自定义的成员提供一个登录控制。我想要做的是设置Thread.CurrentPrincipal到我的自定义Principal对象,用户通过身份验证之后。如何设置Thread.CurrentPrincipal以供整个应用程序使用?

我使用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,将其设置为我设置为CurrentPrincipal对象的主体对象。

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

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

+0

你在做什么?你希望每个人都被识别为第一个登录用户吗?您需要了解Web应用程序身份验证和授权的机制,使用Cookie等。您无法将一个主体设置为所有多用户应用程序线程。 – 2009-08-31 09:03:18

+0

当然不是。也许我没有足够清楚地表达自己。 – Goran 2009-08-31 10:05:50

回答

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; 
} 
+0

让我澄清这更多...我已经使用Forms身份验证,如果您还没有注意到......这只是我想在线程的Identity对象中保存用户ID(以及一些其他用户信息) .CurrentPrincipal,所以我实现了我自己的Principal和Identity对象,并重写了Forms验证的Login控件的Authenticate方法。 – Goran 2009-08-31 08:49:59

+0

我现在就试试这个...... – Goran 2009-08-31 09:04:13

2

Tadas没有错,FormsAuthentication的正确实现不会导致这个问题。

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

这是FormsAuthentication是如何工作的,

  1. 它检查是否验证cookie设置与否,然后引导用户到登录页面
  2. 登录页面必须验证并设置身份验证cookie的,像FormsAuthentication.SetAuthCookie
  3. 每一个页面的访问之前,步骤1执行。
  4. 验证Cookie的成功验证之后,ASP.NET在内部设置当前用户,并根据您的会员组件的所有目前存在的参数。
  5. ASP.NET Global.asax文件可以给你一些事件,在那里你可以插件代码检查刚过认证成功,你可以更改当前用户,记得设置登录页面上的电流原理将不利于

我们有当我们使用会话来存储一些重要的信息,经过身份验证的会议并没有重建类似的问题,所以我们写了一个HTTP模块,并在它的init方法,我们连接AfterRequestAcquired事件,在这个事件中,你可以写你的代码来实例化所有重要的用户相关变量。

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,然后我有序列化问题,我需要修复下一个...谢谢你们...

+0

当我切换到IIS而不是使用Visual Studio Development服务器时,序列化问题就消失了。 – Goran 2009-08-31 13:13:15

相关问题