zoukankan      html  css  js  c++  java
  • 昨晚上写的关于IBuySpy里面用户权限验证方面的东西

    ASP.NET在页面的Context.User里面放了一个实现IPrincipal的对象,用来实现对已验证用户的管理。ASP.NET系统中,通常采用的方式就是扩展这个Context.User,让它里面保存定制的信息。

    1、扩展方式

    扩展方式基本上有两种:直接利用GenericPrincipal和自己写一个实现IPrincipal的类。IBuySpy用的前者,优点就是N简单。

    Context.User = new GenericPrincipal(Context.User.Identity, roles);

    roles是一个保存了当前用户的角色信息的String,各个角色间用“;”分隔,由前面的代码调用数据层中的UserDB.GetRoles()方法来得到。

    自己写一个实现IPrincipal的类其实也是N简单,你只需要实现两个接口:Identity属性返回一个IIdentity的用户标识对象,IsInRole(String role)判断用户是否具有参数中的角色。下面是我写的一个替代IBuySpy中原有扩展模式的类:

    public class IBSPrincipal : IPrincipal {

    private IIdentity _identity;

    private String[] _asRole;

    下面是两个构造函数:

    public IBSPrincipal(IIdentity identity, String roles) {

    _identity = identity;

    _asRole = roles.Split(';');

    }

    public IBSPrincipal(IIdentity identity, String[] roles) {

    _identity = identity;

    _asRole = roles;

    }

    然后是用来实现IPrincipal的一个属性和一个方法:

    public IIdentity Identity {

    get {

    return _identity;

    }

    }

    public bool IsInRole(string role) {

        // 下面一行幸得“JGTM'2003”告知Array有一个static的IndexOf()

        // 原来是用循环查询_asRole....土不可及...

        return (System.Array.IndexOf(_asRole, role) > -1);

    }

    OK,然后我们就可以用下面这句替代上面IBuySpy原有的那句了:

    Context.User = new IBSPrincipal(Context.User.Identity, roles);

    看起来好像自己创建这个IBSPrincipal并不划算,它没有提供比GenericPrincipal更多的功能,但好处是我们以后可以随时扩展它,而且实现的成本也很低。

    2、时机

    我们在什么时候进行上面所说的这样的扩展行为呢?

    IBuySpy选择在Global.asax里面的Application_AuthenticateRequest事件里面进行这些动作,只要ASP.NET程序需要进行用户验证,那么肯定要经过这里,这个地方不错。

    另一个好地方就是在“页面基类”的Page_Init方法中,我们在构造网站的时候就可以先构建一个“页面基类”(即使一开始里面什么都没有),所有的页面都从这个基类继承下来而不是从默认的System.Web.UI.Page,这样做的好处是我们可以随时把类似的动作放在基类中。可惜IBuySpy本身并没有应用这种“页面基类”的方式。

    3、FormsAuthenticationTicket

    这个类是一个“验证票据”类,我们可以利用这个票据来保存用户的信息,并把这个票据写到客户端的Cookie里面,以后客户再来时,从Cookie中把这个票据取回来,就可以得到用户的信息了。

    上面这一段说的就是IBuySpy做的,但是一定要注意,我们自己做这些操作,和ASP.NET内置的Forms验证没有任何关系,虽然它也是通过类似的保存票据到Cookie来实现的。

    用这个票据来写到Cookie与我们自定义一个Cookie去写相比有什么好处呢,首先可以设定票据的过期时间、决定是否永久在Cookie保存票据、票据中可以写入自定义的信息(比如用户所具有的角色),而且,.NET内置的FormsAuthentication.Encrypt()方法和FormsAuthentication.Decrypt()方法可以把一个票据加密成一个字符串,和从一个字符串解密出一个票据,这样省掉了我们很多的工作了。

    来看看IBuySpy里面的代码,创建一个票据并写到Cookie:

    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(

    1,  // version

    Context.User.Identity.Name,  // user name

    DateTime.Now,  // issue time

    DateTime.Now.AddHours(1),  // expires every hour

    false,  // don't persist cookie

    roleStr  // roles

    );

    // Encrypt the ticket

    String cookieStr = FormsAuthentication.Encrypt(ticket);

    // Send the cookie to the client

    Response.Cookies["portalroles"].Value = cookieStr;

    Response.Cookies["portalroles"].Path = "/";

    Response.Cookies["portalroles"].Expires = DateTime.Now.AddMinutes(1);

    从Cookie中读出票据,再从票据中得到用户具有的角色:

    // Get roles from roles cookie

    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(Context.Request.Cookies["portalroles"].Value);

    //convert the string representation of the role data into a string array

    ArrayList userRoles = new ArrayList();

    foreach (String role in ticket.UserData.Split( new char[] {';'} )) {

    userRoles.Add(role);

    }

    roles = (String[]) userRoles.ToArray(typeof(String));

  • 相关阅读:
    LeetCode 83. Remove Duplicates from Sorted List (从有序链表中去除重复项)
    LeetCode 21. Merge Two Sorted Lists (合并两个有序链表)
    LeetCode 720. Longest Word in Dictionary (字典里最长的单词)
    LeetCode 690. Employee Importance (职员的重要值)
    LeetCode 645. Set Mismatch (集合不匹配)
    LeetCode 500. Keyboard Row (键盘行)
    LeetCode 463. Island Perimeter (岛的周长)
    115.Distinct Subsequences
    55.Jump Game
    124.Binary Tree Maximum Path Sum
  • 原文地址:https://www.cnblogs.com/kaneboy/p/2436710.html
Copyright © 2011-2022 走看看