2009-10-12 83 views
10

我正在使用ASP.NET MVC 1.0的应用程序,我试图注入到HttpContext.Current.User对象的自定义IPrincipal对象。ASP.NET MVC自定义IPrincipal注入

对于传统的WebForms应用程序,我使用Application_AuthenticateRequest事件来执行此操作,如下所示。

protected void Application_AuthenticateRequest(object sender, EventArgs e) 
    { 
     if (HttpContext.Current.User != null) 
     { 
      if (HttpContext.Current.User.Identity.IsAuthenticated) 
      { 
       if (HttpContext.Current.User.Identity is FormsIdentity) 
       { 
        // Get Forms Identity From Current User 
        FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity; 
        // Get Forms Ticket From Identity object 
        FormsAuthenticationTicket ticket = id.Ticket; 
        // Create a new Generic Principal Instance and assign to Current User 
        SiteUser siteUser = new SiteUser(Convert.ToInt32(id.Name)); 

        HttpContext.Current.User = siteUser; 
       } 
      } 
     } 

    } 

因此,通过明确地将User对象转换为输入SiteUser来访问我的自定义IPrincipal。我其实是通过拥有一个自定义的类来实现的,所有的页面都是从这个类继承而来的。

无论如何,我的问题是,使用ASP.NET MVC时,Application_AuthenticateRequest似乎在任何请求发生时触发(所以对于JS文件,图像等)导致应用程序死亡。

任何关于如何将自定义IPrincipal注入到ASP.NET MVC 1.0中的HttpContext.Current.User对象的帮助或建议将不胜感激。我确实在SO上看到以下帖子,但它似乎并未满足我想要实现的目标:ASP.NET MVC - Set custom IIdentity or IPrincipal

TIA。

+0

不应该死,无论文件类型 - 你看到什么错误? – blowdart 2009-10-13 10:35:38

+0

我在Application_AuthenticateRequest方法上获得了每个请求的资源的“命中”。与没有使用Application_AuthenticateRequest方法的情况下运行相比,它使页面渲染速度缓慢。 SiteUser对象的构造函数没有做任何特别壮观的事情,只是从DB获取用户详细信息和角色列表。 – 2009-10-13 13:39:22

+0

当然,你做的,这就是IIS7的工作原理 - 我以为你的意思是死于一个错误 – blowdart 2009-10-14 08:54:01

回答

8

我的问题是,与ASP.NET MVC 的Application_AuthenticateRequest 似乎火,只要任何请求 作出(所以JS文件,图像等) 这会导致应用程序终止。

这不是一个独特的MVC问题 - 如果你在地方综合管线跑了您的应用程序IIS7然后你会看到同样的事情。

如果与查找问题是可伸缩性那么我想实际的问题是内

FormsAuthenticationTicket ticket = id.Ticket; 
SiteUser siteUser = new SiteUser(Convert.ToInt32(id.Name)); 

我猜你SiteUser类做某种数据库查找。如果您检查表单身份验证是如何工作的,则票证包含生成FormsIdentity所需的所有信息(这不适用于角色,除非您特别启用角色缓存到cookie)。所以你应该看看同样的方法。第一次构建siteUser对象时,它会将其缓存在一个签名的cookie中,然后使用该cookie在随后的请求中对您的SiteUser属性进行再水化。

如果你这样做,那么你可以更进一步,用你的SiteUser替换Thread原则,或者至少一个与SiteUser类具有相同信息的自定义IPrincipal/IUser组合。

所以里面AuthenticateRequest你有一个像

SiteUserSecurityToken sessionToken = null; 
if (TryReadSiteUserSecurityToken(ref sessionToken) && sessionToken != null) 
{ 
    // Call functions to attach my principal. 
} 
else 
{ 
    if (HttpContext.Current.User != null && 
     HttpContext.Current.User.Identity.IsAuthenticated && 
     HttpContext.Current.User.Identity is FormsIdentity) 
    { 
     // Get my SiteUser object 

     // Create SiteUserSecurityToken 

     // Call functions to attach my principal. 
    } 
} 

一些流量和功能来连接主要将包含类似

HttpContext.Current.User = sessionSecurityToken.ClaimsPrincipal; 
Thread.CurrentPrincipal = sessionSecurityToken.ClaimsPrincipal; 
this.ContextSessionSecurityToken = sessionSecurityToken; 

你会想,以确保其功能将安全令牌写入cookie添加至少一个校验和/ MAC值,如果您愿意,可以使用机器密钥来支持加密(如果已配置)。阅读功能应验证这些值。

+0

非常好,谢谢。我的一个小学生错误!非常感谢。 – 2009-10-14 10:10:29

1

这听起来像是一个custom Authorization Filter的工作。

+0

我确实考虑过这个,但我希望能够以其他方式使用我的强类型用户对象。我希望我不必生成一个自定义的授权过滤器,然后开始在自定义基本控制器类中连接我的用户对象,但看起来可能是要走的路。我真的不想实现自定义成员资格提供者。无论如何,谢谢你的建议:)这看起来很快就像我将被迫采取的做法。 – 2009-10-13 10:45:58

+0

如果你解释*为什么你要注入一个自定义主体,也许还有其他更多的ASP.NET MVC解决你的问题的方法。 – bzlm 2009-10-13 10:59:16