zoukankan      html  css  js  c++  java
  • asp.net mvc 简单实现一个账号只能在一个地方登录

    原理:

        假设用户在机器A登陆后,

        这时用户再次在机器B登陆,会以当前会话的SessionID作为,用户id作为,插入dictionary集合中,集合再保存在application(保存在服务器的全局变量,多用户可以共享)变量中,

             同时判断集合中是否有其他值,这里A机器已经登陆,所以会有A机器登陆的键值对,将A机器的键对应值修改为“_offline_”,以表示强制下线,

        A机器的页面通过js轮询去查询dictionary集合,发现中SessionID键对应的值被修改为“_offline_”,从而注销登陆,并提示被迫下线。

    1、global中的代码:

    public class MvcApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
    
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
            }
    
            //保证同一次会话的SessionID不变
            protected void Session_Start(object sender, EventArgs e) 
            { }
    
            protected void Session_End(object sender, EventArgs e)
            {
                Hashtable hOnline = (Hashtable)Application["Online"];
                if (hOnline != null)
                {
                    if (hOnline[Session.SessionID] != null)
                    {
                        hOnline.Remove(Session.SessionID);
                        Application.Lock();
                        Application["Online"] = hOnline;
                        Application.UnLock();
                    }
                }
            }
        }
    注:保证同一次会话的SessionID不变,这点很重要

    2、用户登陆代码:
    .....
    
    HttpContext httpContext = System.Web.HttpContext.Current;
                var userOnline = 
    (Dictionary<string,string>)httpContext.Application["Online"];
                if (userOnline != null)
                {

                IDictionaryEnumerator enumerator = userOnline.GetEnumerator();
                while (enumerator.MoveNext())
                {
                  if (enumerator.Value != null && enumerator.Value.ToString().Equals(userID.ToString()))
                  {
                    userOnline[enumerator.Key.ToString()] = "_offline_";
                    break;
                  }
                }

                }

    else
                {
                    userOnline = new Hashtable();
                }
                userOnline[Session.SessionID] = userID.ToString();
                httpContext.Application.Lock();
                httpContext.Application["Online"] = userOnline;
                httpContext.Application.UnLock();
    
    ......

    4、页面轮询(可以在母版页,公共页)

    前台js用的easyui

    $(document).ready(function () {
            //定时检测是否被强制下线
                setInterval(function () {
                    CheckIsForcedLogout();
                }, 5000);
        });
    
        //检测是否被强制下线
        function CheckIsForcedLogout() {
            $.ajax({
                url: "/Home/CheckIsForcedLogout",
                type: "POST",
                dataType: "json",
                success: function (msg) {
                    if (msg.OperateResult == "Success") {
                        $.messager.alert('', msg.OperateData, 'error', function () {
                            window.location.href = "/Account/Login";
                        });
                    }
                },
                error: function (ex) { }
            });
        }
     [HttpPost]
            public JsonResult CheckIsForcedLogout()
            {
                try
                {
                    HttpContext httpContext = System.Web.HttpContext.Current;
                    Hashtable userOnline = (Hashtable)httpContext.Application["Online"];if (userOnline != null)
                    {
                        if (userOnline.ContainsKey(httpContext.Session.SessionID))
                        {
                            var value=userOnline[httpContext.Session.SessionID];
                            //判断当前session保存的值是否为被注销值
                            if (value != null && "_offline_".Equals(value))
                            {
                                //验证被注销则清空session
                                userOnline.Remove(httpContext.Session.SessionID);
                                httpContext.Application.Lock();
                                httpContext.Application["online"] = userOnline;
                                httpContext.Application.UnLock();
    
                                string msg = "下线通知:当前账号另一地点登录, 您被迫下线。若非本人操作,您的登录密码很可能已经泄露,请及时改密。";
    
                                //登出,清除cookie
                                FormsAuthentication.SignOut();
    
                                return Json(new { OperateResult = "Success", OperateData = msg }, JsonRequestBehavior.AllowGet);
                            }
                        }
                    }
                    return Json(new { OperateResult ="Failed" }, JsonRequestBehavior.AllowGet);
                }
                catch (Exception ex)
                {
                    return Json(new { OperateResult = "Failed" }, JsonRequestBehavior.AllowGet);
                }
            }

    这里登陆后,每5秒轮询服务器(获取最后登陆时间、ip是从redis缓存读取,所以轮询没有访问数据库),然后不访问数据库,但是数据量大的话,服务器压力也是挺大的,暂时没有更好的解决方案。

  • 相关阅读:
    kubernetes添加不了google apt-key
    The command 'xxx' returned a non-zero code: 100
    gitlab autuo devops
    zabbix监控流程图
    xshell全局设置配色方案
    设置行,列尺寸,权重weight(tkinter,Python3.x)
    Tkinter 的 Text 组件
    Python字符串颜色输出
    tkinter Frame relief属性演示
    Tkinter 的组件 PanedWindow
  • 原文地址:https://www.cnblogs.com/qk2014/p/7988383.html
Copyright © 2011-2022 走看看