当同一个用户ID尝试登录多个设备上,我怎么杀死其他设备上的会话? [英] When the same user ID is trying to log in on multiple devices, how do I kill the session on the other device?

查看:974
本文介绍了当同一个用户ID尝试登录多个设备上,我怎么杀死其他设备上的会话?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要做的是一个用户ID限制为只能够在同一时间登录到一台设备。例如,用户IDABC登录到他们的计算机。用户IDABC现在试图从自己的手机登录。我希望发生是杀死他们的计算机上的会话。

What I want to do is to limit a user ID to only being able to log in to one device at a time. For example, user ID "abc" logs in to their computer. User ID "abc" now tries to log in from their phone. What I want to happen is to kill the session on their computer.

Spotify应用不正是这个 - 的Spotify只允许在同一时间被记录在一个用户ID在一个设备上。

The Spotify app does exactly this- Spotify only allows one User ID to be logged in on one device at a time.

我使用ASP.NET成员资格(SqlMembershipProvider的)和窗体身份验证。

I'm using ASP.NET membership (SqlMembershipProvider) and Forms Authentication.

我已经尝试用Session变量,但我不知道究竟在何处从这里去了。

I've experimented with Session variables but I'm not sure exactly where to go from here.

推荐答案

我想出了一个pretty真棒解决这个。我已经实现了当用户鲍勃的日志从他们的PC,然后在同一个用户从其他位置鲍勃的日志,日志中从第一位置(个人电脑)会被同时允许秒杀登录去住。一旦用户登录,这将记录插入自定义表我创建一个名为登录。一旦成功登录,一个记录将被插入到该表为用户ID的SessionID和的loggedIn的价值观。用户ID是pretty不言自明的,是的SessionID当前会话ID(下如何得到解释),和的loggedIn仅仅是最初的成功后用户登录设置为True布尔。我把这种插入逻辑后,我的成功验证我的AccountController的登录方法内用户可看到如下:

I came up with a pretty awesome solution to this. What I've implemented was when user "Bob" logs in from their PC, and then the same user "Bob" logs in from another location, the log-in from the first location (their PC) will be killed while allowing the second log-in to live. Once a user logs in, it inserts a record into a custom table I created called "Logins". Upon a successful log-in, one record will be inserted into this table with values for "UserId, SessionId, and LoggedIn". UserId is pretty self-explanatory, SessionId is the current Session ID (explained below how to get), and LoggedIn is simply a Boolean that's initially set to True upon a successful user log-in. I place this "insert" logic inside my Login method of my AccountController upon successful validation of the user- see below:

Logins login = new Logins();
login.UserId = model.UserName;
login.SessionId = System.Web.HttpContext.Current.Session.SessionID;;
login.LoggedIn = true;

LoginsRepository repo = new LoginsRepository();
repo.InsertOrUpdate(login);
repo.Save();

有关我的情况,我想放在我的每个控制器的检查,看是否在当前登录用户在登录其他地方,如果是这样,杀对方会话(S)。然后,当杀死会话尝试随时随地浏览我放在这些检查,它会记录出来,将其重定向到登录屏幕。

For my situation, I want to place the check on each of my controllers to see if the currently logged in user is logged in elsewhere, and if so, kill the other session(s). Then, when the killed session tries to navigate anywhere I placed these checks on, it'll log them out and redirect them to the Log-in screen.

我有做这些检查方法主要有三种:

I have three main methods that does these checks:

IsYourLoginStillTrue(UserId, SessionId);
IsUserLoggedOnElsewhere(UserId, SessionId);
LogEveryoneElseOut(UserId, SessionId);

保存会话ID会话[...]

这一切,虽然之前,我的SessionID保存到的AccountController内部会话集合时,登录在 [HttpPost] )方法:

Before all of this though, I save the SessionID to the Session collection inside the AccountController, inside the Login ([HttpPost]) method:

if (Membership.ValidateUser(model.UserName, model.Password))
{
     Session["sessionid"] = System.Web.HttpContext.Current.Session.SessionID;
...

控制器code

我然后把我的逻辑控制器内部控制这三种方法的执行流程。注意低于如果由于某种原因会话[的SessionID] ,这将只是简单地给它分配一个空的价值。这是以防万一由于某种原因,它回来为空:

I then place logic inside my controllers to control the flow of the execution of these three methods. Notice below that if for some reason Session["sessionid"] is null, it'll just simply assign it a value of "empty". This is just in case for some reason it comes back as null:

public ActionResult Index()
{
    if (Session["sessionid"] == null)
        Session["sessionid"] = "empty";

    // check to see if your ID in the Logins table has LoggedIn = true - if so, continue, otherwise, redirect to Login page.
    if (OperationContext.IsYourLoginStillTrue(System.Web.HttpContext.Current.User.Identity.Name, Session["sessionid"].ToString()))
    {
        // check to see if your user ID is being used elsewhere under a different session ID
        if (!OperationContext.IsUserLoggedOnElsewhere(System.Web.HttpContext.Current.User.Identity.Name, Session["sessionid"].ToString()))
        {
            return View();
        }
        else
        {
            // if it is being used elsewhere, update all their Logins records to LoggedIn = false, except for your session ID
            OperationContext.LogEveryoneElseOut(System.Web.HttpContext.Current.User.Identity.Name, Session["sessionid"].ToString());
            return View();
        }
    }
    else
    {
        FormsAuthentication.SignOut();
        return RedirectToAction("Login", "Account");
    }
}

的三种方法

以上是我用它来检查,​​看看是否你还在记录在方法(即确保你不被其他的登录尝试拉开序幕),如果是这样,请检查您的用户ID登录在别处,如果是这样,踢他们关闭的只是自己的loggedIn状态设置为中的登录表。

These are the methods I use to check to see if YOU are still logged in (i.e. make sure you weren't kicked off by another log-in attempt), and if so, check to see if your User ID is logged in somewhere else, and if so, kick them off by simply setting their LoggedIn status to false in the Logins table.

public static bool IsYourLoginStillTrue(string userId, string sid)
{
    CapWorxQuikCapContext context = new CapWorxQuikCapContext();

    IEnumerable<Logins> logins = (from i in context.Logins
                                  where i.LoggedIn == true && i.UserId == userId && i.SessionId == sid
                                  select i).AsEnumerable();
    return logins.Any();
}

public static bool IsUserLoggedOnElsewhere(string userId, string sid)
{
    CapWorxQuikCapContext context = new CapWorxQuikCapContext();

    IEnumerable<Logins> logins = (from i in context.Logins
                                  where i.LoggedIn == true && i.UserId == userId && i.SessionId != sid
                                  select i).AsEnumerable();
    return logins.Any();
}

public static void LogEveryoneElseOut(string userId, string sid)
{
    CapWorxQuikCapContext context = new CapWorxQuikCapContext();

    IEnumerable<Logins> logins = (from i in context.Logins 
                                  where i.LoggedIn == true && i.UserId == userId && i.SessionId != sid // need to filter by user ID
                                  select i).AsEnumerable();

    foreach (Logins item in logins)
    {
        item.LoggedIn = false;
    }

    context.SaveChanges();
}

修改我也想补充一点,code忽略记住我功能的能力。我的要求并不涉及此功能(其实,我的客户不想使用它,出于安全原因),所以我刚刚离开它。用虽然一些额外的编码,我pretty肯定,这可以被考虑进去。

EDIT I just also want to add that this code ignores the capability of the "Remember Me" feature. My requirement didn't involve this feature (in fact, my customer didn't want to use it, for security reasons) so I just left it out. With some additional coding though, I'm pretty certain that this could be taken into consideration.

这篇关于当同一个用户ID尝试登录多个设备上,我怎么杀死其他设备上的会话?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆