蜘蛛侠论坛核心框架分析1 - 如何设计与实现当前访问用户

论坛演示地址:http://www.entityspider.com/ 
源代码下载地址:http://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[0] as 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,这样一来,我们在各个地方就可以很容易的访问我们自定义好的用户对象啦。是不是很简单呢?

 

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

时间: 2024-08-31 06:06:50

蜘蛛侠论坛核心框架分析1 - 如何设计与实现当前访问用户的相关文章

通过分析蜘蛛侠论坛中的版块管理功能来介绍该如何使用我开发出来的ROM框架

 http://www.cnblogs.com/netfocus/archive/2010/01/10/1643207.html  上面这个是框架发布页面的地址.   就以论坛版块管理模块作为例子来介绍这个框架吧,包括显示版块列表.新增版块.修改版块.删除版块四个功能: 1. 表设计: SQL代码 1 CREATE TABLE [tb_Sections](2     [EntityId] [int] IDENTITY(1,1) NOT NULL,3     [Subject] [varchar]

蜘蛛侠论坛 2.0 源代码发布

上次发布了1.0版本,经过两个月的测试,发现和改进了不少问题. 因为今后打算全面开始接触学习ASP.NET MVC源代码和jquery,打算今后用这两个框架打造蜘蛛侠论坛3.0版.所以,今天发布蜘蛛侠论坛基于ASP.NET 2.0 WebForm技术开发的最终版本. 我为这个论坛倾注了很多的个人时间,目的就是希望它功能不断完善,架构不断改进,安全性能不管提升.我想任何事情不能看表面,我在做这个论坛的时候学习过很多有名的开源论坛社区,比如国外的DNN,CommunityServer,或者国内的Di

浅谈12306核心模型设计思路和架构设计

原文:浅谈12306核心模型设计思路和架构设计 春节期间,无意中看到一篇文章,文章中讲到12306的业务复杂度远远比淘宝天猫这种电商网站要复杂.后来自己想想,也确实如此.所以,很想挑战一下12306这个系统的核心领域模型的设计.一般的电商网站,购买都是基于商品的概念,每个商品有一定量的库存,用户的购买行为是针对商品的.当用户发起购买行为时,系统只需要生成订单并对用户要购买的商品减库存即可.但是,12306就不是那么简单了,具体复杂在哪里,我下面会进一步分析.   另外一个让我写这篇文章的原因,是

iOS简易蓝牙对战五子棋游戏设计思路之一——核心蓝牙通讯类的设计

iOS简易蓝牙对战五子棋游戏设计思路之一--核心蓝牙通讯类的设计 一.引言     本系列博客将系统的介绍一款蓝牙对战五子棋的开发思路与过程,其中的核心部分有两个,一部分是蓝牙通讯中对战双方信息交互框架的设计与开发,一部分是五子棋游戏中棋盘逻辑与胜负判定的算法实现.本篇博客将介绍游戏中蓝牙通讯类的设计思路 二.设计通讯类的核心想法    在前篇的一篇博客中,我们有详细的介绍iOS中蓝牙4.0技术的应用与系统框架CoorBluetooth.framework中提供的编程接口的用法.博客地址如下,如

写自己的缓存框架,JAD-CACHE架构设计篇

在之前一篇<写一个自己的通用缓存框架,以同时支持ehcache.mecache以及springcache注解等等>博文中,列出了自己的通用缓存框架需要实现在的大致功能总结如下: 1.提供统一的缓存操作api: 2.支持同时使用多种缓存实现: 3.提供灵活的配置: 4.需要防止缓存穿透: 5.需要可以灵活指定缓存存活时间: 6.需要任意控制缓存的停用或启用. 目前这个框架的编码部分已完成,并取名为JAD-CACHE,取这个名字的原因是因为它是我的个人的JAD项目的一部分,JAD项目是本人用业余时

jquery框架分析-构造jquery对象初步

这是一些分析jquery框架的文字针对jquery 1.3.2版本面向的读者应具备以下要求1.非常熟悉HTML2.非常熟悉javascript语法知识3.熟悉javascript面向对象方面的知识4.熟练使用jquery框架 言归正传!jquery对象的初始化是写在匿名函数里的就像这样: (function(){alert("jquery框架分析")})(); 第一个括号是声明了一个函数,第二个括号是执行这个函数 也就是说,jquery框架在页面载入的时候已经做了一些事情(这个个匿名函

Linux USB驱动框架分析【转】

转自:http://blog.csdn.net/jeffade/article/details/7701431 Linux USB驱动框架分析(一) 初次接触和OS相关的设备驱动编写,感觉还挺有意思的,为了不至于忘掉看过的东西,笔记跟总结当然不可缺,更何况我决定为嵌入式卖命了.好,言归正传,我说一说这段时间的收获,跟大家分享一下Linux的驱动研发.但这次只先针对Linux的USB子系统作分析,因为周五研讨老板催货.当然,还会顺带提一下其他的驱动程式写法. 事实上,Linux的设备驱动都遵循一个

Linux USB驱动框架分析(2)【转】

转自:http://blog.chinaunix.net/uid-23046336-id-3243543.html   看了http://blog.chinaunix.net/uid-11848011-id-96188.html的驱动框架分析,感觉受益匪浅.对于一些内容,我自己查漏补缺. 首先我们按照顺序,看内核模块的注册以及释放函数如下: 点击(此处)折叠或打开 static int __init usb_skel_init(void) {     int result;     /* reg

Alsa音频子系统Codec---al5623.c内核代码框架分析

驱动代码位于: sound/soc/codec/alc5623.c 随便找个linux内核都会有. 1.首先进行i2c总线驱动加载在: static int __init alc5623_modinit(void)在该函数中: i2c_add_driver(&alc5623_i2c_driver);alc5623_i2c_driver是一个结构体变量,并且已经被初始化,我们来看看它做了什么? static struct i2c_driver alc5623_i2c_driver = { .dri