天天看点

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

蜘蛛侠论坛采用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

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

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();

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

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

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

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

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

这里我为了突出重点,所以把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

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

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);

private static void initializeuser(user user)

        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;

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

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

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

\business\controls\forumusercontrol.cs

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

public class forumusercontrol : baseusercontrol

    protected forumuser currentuser

            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);

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

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

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