限制同一账号多处登录

原文:

http://wenku.baidu.com/link?url=x0keBGHull3vEYGXQxVyYJEW9iRMnkcHGMph3DquT9Uc0Y4cGh0CNmlIIa4trsmQEufXR0Cm9CSLfhptTF144OLf07V3CNav4hcoeowHhTW#

SignOnMode.cs

#region
// -----------------------------------------------------------------
// 版权所有:Copyright(C) 
// 文件名称:SignOnMode.cs
// 系统名称:
// 模块名称:
// 作  者:Keasy5
// 完成日期:2015/12/24 9:51:10
// 功能描述:
// -----------------------------------------------------------------
// 修 改 者:
// 修改日期:
// 修改描述:
// -----------------------------------------------------------------
#endregion

using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using DocumentFormat.OpenXml.Packaging;

namespace Common.Function.Login
{
    /// <summary>
    /// 登录方式类
    /// </summary>
    /// <remarks>
    /// 同一账号是否能在多处登录帮助类
    /// </remarks>
    public static class SignOnMode
    {
        /// <summary>
        /// 在线信息Application标识
        /// </summary>
        private const string OnlineAppFlag = "Online";

        private const string InvalidSessionFlag = "INVALIDSESSION";

        /// <summary>
        /// 添加登录信息
        /// </summary>
        /// <param name="signOnToken">
        /// 登录令牌:用于标识用户信息的唯一标识,一般是用户的id
        /// </param>
        public static void RegisterSignOn(string signOnToken)
        {
            Hashtable hOnline = (Hashtable)HttpContext.Current.Application[OnlineAppFlag];
            if (hOnline != null)
            {
                IDictionaryEnumerator enumerator = hOnline.GetEnumerator();
                string sessionId = "";
                while (enumerator.MoveNext())
                {
                    if (enumerator.Value != null && enumerator.Value.ToString().Equals(signOnToken))
                    {
                        /*
                         * 将当前用户Id对应的会话(Session.SessionID唯一标识)
                         * 都设置为无效会话
                         */
                        sessionId = enumerator.Key.ToString();
                        hOnline[sessionId] = InvalidSessionFlag; //无效会话
                        break;
                    }
                }
            }
            else
            {
                hOnline = new Hashtable();
            }

            //将当前"登录"用户Id对应的会话设置为有效会话
            hOnline[HttpContext.Current.Session.SessionID] = signOnToken;
            HttpContext.Current.Application.Lock();
            HttpContext.Current.Application[OnlineAppFlag] = hOnline;
            HttpContext.Current.Application.UnLock();
        }

        /// <summary>
        /// 是否需要强制退出当前登录
        /// </summary>
        /// <returns>
        /// 是否退出登录:
        /// true:表示当前登录需要当前强制退出
        /// 否则:当前当前登录不需要退出
        /// </returns>
        public static bool NeedForceSignOut()
        {
            bool needForcedSignOut = false; //是否需要强制退出当前登录

            // 配置:同一账号是否能在多处登录
            string canMultipleLogin = ConfigurationManager.AppSettings["CanMultipleLogin"];
            if (canMultipleLogin != null && canMultipleLogin.ToLower() == "true")
            {
                return false; //同一账号可以能在多处登录
            }

            Hashtable hOnline = (Hashtable)HttpContext.Current.Application[OnlineAppFlag];
            if (hOnline != null && HttpContext.Current.Session != null)
            {
                IDictionaryEnumerator enumerator = hOnline.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    var sessionId = enumerator.Key;
                    var sessionVal = enumerator.Value;

                    if (sessionId != null && sessionId.ToString().Equals(HttpContext.Current.Session.SessionID))
                    {
                        if (sessionVal != null && InvalidSessionFlag.Equals(sessionVal.ToString()))
                        {
                            /*删除无效会话*/
                            hOnline.Remove(HttpContext.Current.Session.SessionID);
                            HttpContext.Current.Application.Lock();
                            HttpContext.Current.Application[OnlineAppFlag] = hOnline;
                            HttpContext.Current.Application.UnLock();

                            //帐号已在别处登陆,被强迫下线!
                            needForcedSignOut = true;
                        }
                        break;
                    }
                }
            }

            return forcedSignOut;
        }

        /// <summary>
        /// 清除无效登录信息
        /// </summary>
        /// <remarks>
        /// 一般用于Global.asax.cs的函数:
        ///     protected void Session_End(object sender, EventArgs e)
        ///  中调用,使得在Session过期或者退出系统时释放资源
        /// </remarks>
        public static void ClearInvalidSignOn()
        {
            if (HttpContext.Current != null)
            {
                Hashtable hOnline = (Hashtable)HttpContext.Current.Application[OnlineAppFlag];
                if (hOnline != null)
                {
                    if (HttpContext.Current.Session != null)
                    {
                        if (hOnline[HttpContext.Current.Session.SessionID] != null)
                        {
                            hOnline.Remove(HttpContext.Current.Session.SessionID);
                            HttpContext.Current.Application.Lock();
                        }
                    }
                }
            }
        }
    }
}
文件:SessionKeys.cs
    /// <summary>
    /// 系统级别Session名称
    /// </summary>
    public static class SessionKeys
    {
        /// <summary>
        ///  存储用户登录的session名常量
        /// </summary>
        public const string LoginUser = "LoginUser";

    }

 文件SessionHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace xxxx
{
    /// <summary>
    /// Session 操作类
    /// 1、GetSession(string name)根据session名获取session对象
    /// 2、SetSession(string name, object val)设置session
    /// </summary>
    public class SessionHelper
    {
        /// <summary>
        /// 根据session名获取session对象
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static object GetSession(string name)
        {
            return HttpContext.Current.Session[name];

        }

        /// <summary>
        /// 设置session
        /// </summary>
        /// <param name="name">session 名</param>
        /// <param name="val">session 值</param>
        public static void SetSession(string name, object val)
        {
            if (KeysContains(name))
            {
                HttpContext.Current.Session[name] = val;
            }
            else
            {
                HttpContext.Current.Session.Add(name, val);
            }
        }

        /// <summary>
        /// 判断Key值在当前Session是不是已经存在
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private static bool KeysContains(string key)
        {
            if (HttpContext.Current.Session != null)
            {
                foreach (var item in HttpContext.Current.Session.Keys)
                {
                    if (item != null && item.Equals(key))
                        return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 添加Session,调动有效期为20分钟
        /// </summary>
        /// <param name="strSessionName">Session对象名称</param>
        /// <param name="strValue">Session值</param>
        public static void Add(string strSessionName, object strValue)
        {
            HttpContext.Current.Session[strSessionName] = strValue;
            HttpContext.Current.Session.Timeout = 120;
        }

        /// <summary>
        /// 添加Session,调动有效期为20分钟
        /// </summary>
        /// <param name="strSessionName">Session对象名称</param>
        /// <param name="strValues">Session值数组</param>
        public static void Adds(string strSessionName, string[] strValues)
        {
            HttpContext.Current.Session[strSessionName] = strValues;
            HttpContext.Current.Session.Timeout = 120;
        }

        /// <summary>
        /// 添加Session
        /// </summary>
        /// <param name="strSessionName">Session对象名称</param>
        /// <param name="strValue">Session值</param>
        /// <param name="iExpires">调动有效期(分钟)</param>
        public static void Add(string strSessionName, object strValue, int iExpires)
        {
            HttpContext.Current.Session[strSessionName] = strValue;
            HttpContext.Current.Session.Timeout = iExpires;
        }

        /// <summary>
        /// 添加Session
        /// </summary>
        /// <param name="strSessionName">Session对象名称</param>
        /// <param name="strValues">Session值数组</param>
        /// <param name="iExpires">调动有效期(分钟)</param>
        public static void Adds(string strSessionName, string[] strValues, int iExpires)
        {
            HttpContext.Current.Session[strSessionName] = strValues;
            HttpContext.Current.Session.Timeout = iExpires;
        }

        /// <summary>
        /// 读取某个Session对象值
        /// </summary>
        /// <param name="strSessionName">Session对象名称</param>
        /// <returns>Session对象值</returns>
        public static string Get(string strSessionName)
        {
            if (HttpContext.Current.Session[strSessionName] == null)
            {
                return null;
            }
            else
            {
                return HttpContext.Current.Session[strSessionName].ToString();
            }
        }

        /// <summary>
        /// 读取某个Session对象值数组
        /// </summary>
        /// <param name="strSessionName">Session对象名称</param>
        /// <returns>Session对象值数组</returns>
        public static string[] Gets(string strSessionName)
        {
            if (HttpContext.Current.Session[strSessionName] == null)
            {
                return null;
            }
            else
            {
                return (string[])HttpContext.Current.Session[strSessionName];
            }
        }

        /// <summary>
        /// 删除某个Session对象
        /// </summary>
        /// <param name="strSessionName">Session对象名称</param>
        public static void Del(string strSessionName)
        {
            HttpContext.Current.Session[strSessionName] = null;
        }

        /// <summary>
        /// 获取Session 过期时间
        /// </summary>
        /// <returns></returns>
        public static int SessionTimeout(string sessionTimeoutConfigString)
        {
            string sessionTimeout = sessionTimeoutConfigString;
            if (string.IsNullOrWhiteSpace(sessionTimeout))
            {
                //如果为空,默认30
                return 30;
            }

            return Convert.ToInt32(sessionTimeout);
        }
    }
}
View Code

使用:

第一步:在登录成功后,记录登录信息

  SignOnMode.RegisterSignOn(user.Id);

public string Login(LoginViewModel model,bool rememberAccount)
 {
    //.......
     if(登录成功)
    {
HttpContext.Current.Session[
SessionKeys.LoginUser] = ....;//用户登录信息,如果该值为null,视为没有登录

SignOnMode.RegisterSignOn(user.Id);
}

//.......
}

第二步:

在需要登录的地方执行 

bool forcedLogout = SignOnMode.NeedForceSignOut();
这里是定义个筛选器,然后在使用在Controller上。
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var _url = "~/Home/Index";

            if (HttpContext.Current.Session[SessionKeys.LoginUser] == null)
            {
                filterContext.Result = new RedirectResult(_url);
            }
            else
            {
                #region 同一账号不能多处登录
                /*--------------------------------------------------------------------------
                 同一账号不能多处登录
                 *--------------------------------------------------------------------------*/

                bool needForceSignOut = SignOnMode.NeedForceSignOut();
                if (needForceSignOut)
                {
                    HttpContext.Current.Session[SessionKeys.LoginUser] = null; //用户登录信息,如果该值为null,视为没有登录 filterContext.Result
= new RedirectResult(_url); } #endregion } }
    [LoginFilter]
    public class BaseController : Controller
    {
         ......     
    }

第三步:在Session过期或者(异常)退出系统时,释放资源释放资源,做法是:

在Global.asax.cs的函数:

  protected void Session_End(object sender, EventArgs e)

中调用:

    SignOnMode.ClearInvalidSignOn();

使得在Session过期或者退出系统时释放资源

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
....
}
protected void Session_End(object sender, EventArgs e) { /*-------------------------------------------------------------------------- 同一账号不能多处登录 *--------------------------------------------------------------------------*/ /*在Session过期或者退出系统时释放资源*/ SignOnMode.ClearInvalidSignOn(); } }

 第四步:

   在配置文件添加中添加“同一账号是否能多处登录”的开关。

  <appSettings>
    <!--配置:同一账号是否能多处登录,true表示可以多点登陆-->
    <add key="CanMultipleLogin" value="false" />
  </appSettings>

 完毕。

原文地址:https://www.cnblogs.com/easy5weikai/p/5072608.html