zoukankan      html  css  js  c++  java
  • 蜘蛛侠论坛核心框架分析1 如何设计与实现当前访问用户

    论坛演示地址:http://www.entityspider.com/
    源代码下载地址:https://files.cnblogs.com/netfocus/Forum.rar

    蜘蛛侠论坛采用Forms验证方式。

    1: 当用户输入用户名和密码并登陆, 此时, 我们会将当前用户的身份标识保存到客户端:

    文件:

    \Core\Managers\MemberManager.cs

    代码:

    CookieManager.AddCookieToResponse(
    FormsAuthentication.GetAuthCookie(member.MemberId.Value.ToString(), 
    false), expireDays);

    2: 用户登陆后, ASP.NET下次就自动知道当前访问用户的身份标识了. 我们可以通过如下方式获取当前登陆用户的标识:

    HttpContext.Current.User.Identity.Name

    另外, 如何判断一个用户是否处于登陆状态? 我们可以通过如下的方式来判断:

    HttpContext.Current.Request.IsAuthenticated

    如果该属性返回TRUE,则表示当前用户已登陆,否则,表示未登陆。

    3: 在什么时候获取当前用户的所有信息?

    ASP.NET提供了一个时机,让我们对用户执行身份验证。该时机就是Application对象的AuthenticateRequest事件。所以,我们可以在该事件的处理函数中确定当前访问用户是否已经登陆,

    文件:

    \Core\Components\Common\HttpModule.cs

    代码:

    private void Application_AuthenticateRequest(Object source, EventArgs e)
    {
        HttpRequest request 
    = HttpContext.Current.Request;

        
    if (request.Url.LocalPath.ToLower().EndsWith(".aspx")
            
    || request.Url.LocalPath.ToLower().EndsWith(".ashx"))
        {
            SetCurrentUser();
        }
    }
    private void SetCurrentUser()
    {
        
    if (!HttpContext.Current.Request.IsAuthenticated)
        {
            
    HttpContext.Current.User = UserManager.GetAnonymousUser();
        }
        
    else
        {
            
    try
            {
                User user 
    = UserManager.GetUser(new Guid(HttpContext.Current.User.Identity.Name));
                
    if (user != null)
                {
                    
    HttpContext.Current.User = user;
                }
                
    else
                {
                    MemberManager.Logout();
                    HttpContext.Current.User 
    = UserManager.GetAnonymousUser();
                }
            }
            
    catch
            {
                MemberManager.Logout();
                HttpContext.Current.User 
    = UserManager.GetAnonymousUser();
            }
        }
    }

    大家可以看到,我们在AuthenticateRequest事件的处理函数中确定一个当前用户,SetCurrentUser函数实现该功能。该函数首先判断当前用户是否已经登陆,如果未登陆,则获取一个匿名用户对象,并赋值给HttpContext.Current.User;如果已经登陆,则根据用户标识从数据库获取登陆用户对象,并同样把该用户对象赋值给HttpContext.Current.User;这里有一个很关键的问题,我们为什么可以把当前获取的用户对象赋值给HttpContext.Current.User?其实很简单,我们只要让我们自己定义的User类实现IPrinciple接口即可,User类的代码如下:

    public class User : Entity, IPrincipal
    {
        
    private IIdentity identity = null;

        
    #region Implementation of IPrincipal

        
    public IIdentity Identity
        {
            
    get
            {
                
    return identity;
            }
            
    set
            {
                identity 
    = value;
            }
        }
        
    public bool IsInRole(string roleName)
        {
            
    //Return true or false by your own logic.
            return false;
        }

        
    #endregion
    }

    这里我为了突出重点,所以把User类的其他不相关的东西删除了。大家可以看到,我们只要让User类实现IPrinciple接口就行了。然后我们可以为User类包含很多我们自定义的属性。

    这样的做法有什么好处呢?其实我们也完全可以把当前用户放在Session或Cache等其他地方。我觉得最大的好处就是自然,因为ASP.NET提供给我们的HttpContext.Current.User对象的意图就是表示当前发送请求的用户实例,但因为该对象所存储的信息非常少,基本上就只存放了一个标识当前登陆用户的标识(如用户名)。但大部分情况下,我们都需要更多的用户信息,所以就自然而然很容易想到扩展该User属性。

    当然还有一个需要说明的细节是,

    因为我们自己创建了一个新的User对象,并且赋值给了HttpContext.Current.User,而赋值之前,HttpContext.Current.User.Identity不为空,所以为了一致,我们也应该给我们自己定义的User类的Identity属性赋值。

    文件:

    \Core\UserRolePermissions\User.cs

    代码:

    public static User GetAnonymousUser()
    {
        User user 
    = Activator.CreateInstance(Configuration.Instance.UserType) as User;
        user.SetRoles(Configuration.Instance.AnonymousDefaultRoleList);
        
    user.Identity = new GenericIdentity(string.Empty);
        
    return user;
    }
    public static User GetUser(Guid memberId)
    {
        TRequest
    <User> request = new TRequest<User>();
        request.Data 
    = Activator.CreateInstance(Configuration.Instance.UserType) as User;
        request.Data.MemberId.Value 
    = memberId;
        EntityList users 
    = Engine.GetAll(request);
        User user 
    = null;
        
    if (users.Count > 0)
        {
            user 
    = users[0as User;
        }
        
    if (user != null)
        {
            InitializeUser(user);
        }
        
    return user;
    }
    private static void InitializeUser(User user)
    {
        
    if (user != null)
        {
            TEntityList
    <Role> roles = new TEntityList<Role>();
            
    foreach (UserAndRole userAndRole in RoleManager.GetUserRoles(user.EntityId.Value))
            {
                roles.Add(userAndRole.Role);
            }
            user.SetRoles(roles);
            
    user.Identity = HttpContext.Current.User.Identity;
        }
    }

    大家可以看到黄色高亮度显示的那几行代码,我对Identity属性进行了赋值。

    4: 如何在页面中访问当前用户?

    文件:

    \Business\Controls\ForumUserControl.cs

    代码:

    public class ForumUserControl : BaseUserControl
    {
        
    protected ForumUser CurrentUser
        {
            
    get
            {
                
    return HttpContext.Current.User as ForumUser;
            }
        }

        
    protected bool ValidatePermission(PermissionType permission)
        {
            
    return CurrentUser.GetPermissions().ValidatePermission((long)permission);
        }
        
    protected bool ValidatePermission(PermissionType permission, Entity entity)
        {
            
    return CurrentUser.GetPermissions(entity).ValidatePermission((long)permission);
        }
    }

    ForumUserControl是一个基类UserControl,我们可以在该控件中提供一个表示当前登陆用户的属性CurrentUser,这样一来,我们在各个地方就可以很容易的访问我们自定义好的用户对象啦。是不是很简单呢?

    好了, 以上就是蜘蛛侠论坛中当前登陆用户的设计与实现。因为觉得可能对大家有用,所以写出来与大家分享。

  • 相关阅读:
    SVG:中国地图
    网页编程工具:EditPlus
    js插件
    html: 仿制soundmanager2右上角面板
    代码:页面布局(含图片列表布局)
    写着玩: 图片 圆盘
    表格
    按钮
    插件:左侧下拉菜单
    颜色
  • 原文地址:https://www.cnblogs.com/netfocus/p/1682871.html
Copyright © 2011-2022 走看看