简单的重复登录控制(ASP.NET版)

延续简单的重复登录控制(java版)中的思路,用ASP.NET做了类似的实现。

 

第一步,构造一个简单的在线会员对象。

[Serializable]
public class OnlineMember
{
    /// <summary>
    /// MemberID
    /// </summary>
    public int MemberID { get; set; }

    /// <summary>
    /// SessionID
    /// </summary>
    public string SessionID { get; set; }

    /// <summary>
    /// 最后通知时间
    /// </summary>
    public DateTime LastNotifyTime { get; set; }

    /// <summary>
    /// 登录IP
    /// </summary>
    public string LoginIP { get; set; }
}

 

第二步,实现在线会员处理功能。

/// <summary>
/// 简易在线会员功能
/// 遵循类似QQ登录的原则:同一帐号登录,总是后登录的挤掉前登录的
/// </summary>
public class OnlineBiz
{
    private static Dictionary<int, OnlineMember> _onlineMember = new Dictionary<int, OnlineMember>();
    private static object _syncObj = new object();
    private static DateTime _lastClearTime = DateTime.Now;

    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="MemberID"></param>
    /// <param name="SessionID"></param>
    /// <param name="LoginIP"></param>
    public static void Add(int MemberID, string SessionID, string LoginIP)
    {
        lock (_syncObj)
        {
            if (_onlineMember.ContainsKey(MemberID))
            {
                _onlineMember.Remove(MemberID);
            }

            OnlineMember member = new OnlineMember();
            member.MemberID = MemberID;
            member.SessionID = SessionID;
            member.LoginIP = LoginIP;
            member.LastNotifyTime = DateTime.Now;

            _onlineMember.Add(MemberID, member);
        }
    }

    /// <summary>
    /// 当前会员是否有效
    /// </summary>
    /// <param name="MemberID"></param>
    /// <param name="SessionID"></param>
    /// <returns></returns>
    public static bool IsValid(int MemberID, string SessionID)
    {
        if (!_onlineMember.ContainsKey(MemberID))
            return false;

        if (!_onlineMember[MemberID].SessionID.Equals(SessionID))
            return false;

        _onlineMember[MemberID].LastNotifyTime = DateTime.Now;

        ClearTimeoutMember();

        return true;
    }

    /// <summary>
    /// 移除
    /// </summary>
    /// <param name="MemberID"></param>
    public static void Remove(int MemberID)
    {
        if (_onlineMember.ContainsKey(MemberID))
            _onlineMember.Remove(MemberID);
    }

    /// <summary>
    /// 清除超时会员
    /// </summary>
    private static void ClearTimeoutMember()
    {
        int MemberLoginTimeout = int.Parse(ConfigHelper.GetParameterValue("MemberLoginTimeout"));
        TimeSpan time1 = DateTime.Now - _lastClearTime;

        if (time1.Minutes > MemberLoginTimeout * 5)
        {
            lock (_syncObj)
            {
                _lastClearTime = DateTime.Now;

                foreach (KeyValuePair<int, OnlineMember> kvp in _onlineMember)
                {
                    TimeSpan time2 = DateTime.Now - kvp.Value.LastNotifyTime;

                    if (time2.Minutes > MemberLoginTimeout)
                    {
                        _onlineMember.Remove(kvp.Key);
                    }
                }
            }
        }
    }
}

 

第三步,在会员登录成功时将会员放入队列。

//将当前会员写入在线列表
OnlineBiz.Add(member.MemberID, Session.SessionID, log.LoginIP);

 

第四步,实现一个在线状态维护的轮询功能,比如用AJAX定时读取某个页面,该页面中进行会员有效性检查。

//当前会员是否有效,重复登录的会员遵循后登录的挤掉前登录的原则
if (!OnlineBiz.IsValid(member.MemberID, context.Session.SessionID))
{
    context.Session.Clear();
    context.Response.Write(context.Request.QueryString["jsoncallback"] + "({result: 0})");
    return;
}

 同时,为了保证严谨性,使已踢掉的登录不能继续操作,还可在页面基类中进行同样的检查。

 

第五步,在客户端进行提示。

if (json.result == 0) {
    alert("本帐号已在别处登录,你已被迫下线!");
    self.location = "<%=Request.ApplicationPath%>/";
    return;
}

 

需要说明的是,“超时会员清理”采用了一个偷懒且不严谨的处理方式:

  1. 清理动作由轮询页面触发,当后续没有会员在线的情况下,不会执行该操作。
  2. 假设会员超时时间为20分钟,为了稍许提高性能,我的代码每100分钟以上才会做次扫描,剔除已超时的会员。
  3. 假设会员超时时间为20分钟,轮询间隔时间应当小于它,比如设为2分钟、5分钟之类的比较合适。

 

该功能已在实际系统中应用,暂时没有发现特别的问题,若你采用了这种处理方式,发现其中存在问题,请告知我。

转载于:https://www.cnblogs.com/wenjian/archive/2010/04/27/1721902.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值