none
HttpContext.Current.User的使用疑问。 RRS feed

  • 问题

  • 我新建了一个类继承并且扩展了IPrincipal接口。代码如下:
    public class YingKePrincipal : IPrincipal
        {
            private YingKeIdentity identity;
    
            public YingKePrincipal(YingKeIdentity identity)
            {
                this.identity = identity;
            }
    
            public IIdentity Identity
            {
                get { return identity; }
            }
    
            public bool IsInRole(string role) {
                return false;
            }
    
            public bool HasPermission()
            {
                return true;
            }
        }
    

    当我去获得HasPermission()方法时,我注意到,HttpContext.Current.User是IPrincipal类型的对象。我的vs无法自动感知到这个扩展方法。手动写上这个方法后,系统也会报错如下:
     
    错误 10 “System.Security.Principal.IPrincipal”不包含“HasPermission”的定义,并且找不到可接受类型为“System.Security.Principal.IPrincipal”的第一个参数的扩展方法“HasPermission”(是否缺少 using 指令或程序集引用?) D:\Work\OA\YingKe.Web\WebForm1.aspx.cs 25 37 YingKe.Web
     
    根据错误提示,我能明确的知道:HttpContext.Current.User是IPrincipal类似而不是我的扩展类型YingKePrincipal。仔细检查代码后,我发现User.Identity属性返回的是YingKeIdentity对象(VS中提示 IIdentity IPrincipal.Identity 通过 IPrincipal的Identity 属性返回了YingKeIdentity对象)。我对用户的扩展属性和方法写YingKeIdentity类中即可达到扩展.NET用户验证机制的目的。
    但是,我想知道的是:为什么.NET要设计的如此繁琐呢?在.NET中,Identity 代表了用户标识;IPrincipal则代表了用户本身。为什么要把他区分开呢?我认为设计成一个类去实现才是最好的!求各位朋友帮忙解惑。谢谢大家!
    2011年10月4日 15:56

答案

  • 你需要自己创建一个IPrincipal的实现。比如在访问需要Windowes身份之前设置一个WindowsPrincipal到Thread.CurrentPrincipal,或者在AuthenticateRequest的时候从HttpContext.Current.User.Identity和HttpContext.Current.Cache创建自己的Principal或者Identity,然后设置到HttpContext.Current.User和Thread.CurrentPrincipal。

    cookie是不可靠的,你不会想让用户用浏览器把自己改成管理员吧?

    如果你把session放在内存里的话,session也是不可靠的,应用程序池回收你的application domain的时候,session会丢掉。

    另外,你写需要权限的代码的时候,是每次都去访问Cookie简单,还是直接写HttpConext.Current.User.IsInRole或者在方法上加[PrincipalPermission(SecurityAction.Demand, Role = "Administrator")]简单?



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    2011年10月8日 16:32
    版主

全部回复

  • Identity指明用户是谁。principal指明用户能做什么。在程序的生命期内,同一个用户的Identity不变,但是权限可能随模块的需求而变化,所以需要区分开。比如如果你的网站有blog何论坛,你可以从同一个Identity创建BlogPrincipal和ForumPrincipal,使得同一个用户可以在不同的模块有不同的角色,同时避免无谓地加载多余的权限数据。



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    2011年10月4日 19:32
    版主
  • MVP果然不一般。

    有两个问题想继续问您:IPrincipal代表用户能做什么。可是我如何获取这个类的引用?或者说我如何使用这个类。

     

    另外,为了提高效率,IPrincipal中的方法一般考虑会存cookie或者session。(直连数据库进行查询的话,浪费效率),这时,IPrincipal还有什么意义?它比直接使用cookie或者session的优势在哪?

     

    2011年10月8日 7:42
  • 你需要自己创建一个IPrincipal的实现。比如在访问需要Windowes身份之前设置一个WindowsPrincipal到Thread.CurrentPrincipal,或者在AuthenticateRequest的时候从HttpContext.Current.User.Identity和HttpContext.Current.Cache创建自己的Principal或者Identity,然后设置到HttpContext.Current.User和Thread.CurrentPrincipal。

    cookie是不可靠的,你不会想让用户用浏览器把自己改成管理员吧?

    如果你把session放在内存里的话,session也是不可靠的,应用程序池回收你的application domain的时候,session会丢掉。

    另外,你写需要权限的代码的时候,是每次都去访问Cookie简单,还是直接写HttpConext.Current.User.IsInRole或者在方法上加[PrincipalPermission(SecurityAction.Demand, Role = "Administrator")]简单?



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    2011年10月8日 16:32
    版主