简单的重复登录控制(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分钟之类的比较合适。

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

优质内容筛选与推荐>>
1、被逮到一个初始状态考虑不周的Bug
2、基础学习
3、Android AlertDialog 详解
4、Vue.js 创建一个 CNODE 社区(7)
5、Maven编译时,出现找不到符号


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号