简体   繁体   English

在asp.net网站中如何防止同一用户ID的多次登录?

[英]In asp.net site how to prevent multiple logins of same user id?

Please guide how to prevent multiple user to be logged in at a time using a user id ? 请指导如何使用用户ID一次防止多个用户登录?

I searched the internet and found some ways but somehow they do not work in these situations: 我搜索了互联网并找到了一些方法,但不知怎的,他们在这些情况下不起作用:

  1. If javascript in brower is turned off. 如果brower中的javascript被关闭。
  2. If user do not click logout and directly close brower. 如果用户没有单击注销并直接关闭浏览器。

Please suggest me some way. 请给我一些建议。

thanks 谢谢

haansi haan​​si

We implemented a system for this along the following lines: 我们按照以下方针为此实施了一个系统:

  • Added a property to the users Profile to hold their session ID. 为用户配置文件添加了一个属性以保存其会话ID。
  • Whenever a user logs in, store their session ID in the Profile. 每当用户登录时,将其会话ID存储在配置文件中。
  • On any page that requires a this level of security, check to see if the session ID stored in the profile matches their session. 在需要此级别安全性的任何页面上,检查存储在配置文件中的会话ID是否与其会话匹配。 This check could be performed in a custom AuthorizeRequest event handler, or it could be performed in a Base class that these pages derive from, and if not, redirect them to the login page. 此检查可以在自定义AuthorizeRequest事件处理程序中执行,也可以在这些页面派生自的Base类中执行,如果不是,则将它们重定向到登录页面。

We went for the base class option as we have two levels of authentication: 我们选择了基类选项,因为我们有两个级别的身份验证:

  1. The user has a cookie token to prove that they have logged in at some point in the past - this is fine for showing them restricted site content. 用户有一个cookie令牌来证明他们已经在过去的某个时间点登录 - 这对于向他们显示受限制的站点内容很好。
  2. The user has actually provided their login details this session - this is required when showing them any personal details (email addresses, preferences, saved job searches, etc). 用户实际上已在此会话中提供了他们的登录详细信息 - 在向他们显示任何个人详细信息(电子邮件地址,首选项,保存的工作搜索等)时,这是必需的

The main issues you'll find with almost any system: 您几乎可以在任何系统中找到的主要问题:

  1. Using the users IP address is unreliable - corporate users, those behind proxies, etc, often share an IP address, so would "appear" to be the same user. 使用用户IP地址是不可靠的 - 企业用户,代理人之后的人等经常共享一个IP地址,因此“看起来”是同一个用户。
  2. Relying on a user to log out is unreliable - the users computer/browser might crash not giving them the opportunity to log out, the user can/will forget to log out. 依赖用户注销是不可靠的 - 用户计算机/浏览器可能崩溃而不给他们注销的机会,用户可能/将忘记注销。
  3. Relying on session time-outs is unreliable - if you're not using InProc sessions, the SessionEnd event never fires, if your server crashes the event isn't called, etc. 依赖会话超时是不可靠的 - 如果您没有使用InProc会话,则SessionEnd事件永远不会触发,如果您的服务器崩溃,则不会调用该事件等。

The issues you'll find with a solution like mine are: 您可以通过我的解决方案找到的问题是:

  1. It doesn't stop the second user logging in - instead it will lock out the first user, which should discourage sharing of details in the first place. 它不会阻止第二个用户登录 - 而是会锁定第一个用户,这应该首先阻止共享细节。
  2. If you don't implement this as an AuthorizeRequest handler you have to remember perform the check on the pages that should be locked down. 如果您没有将其实现为AuthorizeRequest处理程序,则必须记住对应该锁定的页面执行检查。

Responding to comment 回应评论

In response to your specific queries: 针对您的具体问题:

  1. The default Profile Provider stores the data in the same SQL database as the membership provider (the tables are created along with the membership and roles tables). 默认的Profile Provider将数据存储在与成员资格提供程序相同的SQL数据库中(这些表与成员资格和角色表一起创建)。 If you were to store it "in the cache" this would need to be the global application cache, along the lines KMan suggests in option 2 - and as pointed out the comments, you'd need to build a time-out for this, and that leads back to the issue of reliably determining this. 如果你要将它“存储在缓存中”,那么这就需要是全局应用程序缓存, 就像KMan在选项2中所建议的那样 - 并且正如指出的那样,你需要为此建立一个超时,这导致了可靠地确定这一点的问题。
  2. The user doesn't log out: This is handled in our system by not locking out future users, but by locking out previously logged in users - so: 用户不会注销:这是在我们的系统中处理的,不会锁定未来的用户,而是锁定以前登录的用户 - 所以:
    • Alice comes to the site, logs in, starts browsing. Alice来到该网站,登录,开始浏览。
    • Bob comes to the site, and logs in with Alice's details, starts browsing. Bob来到该网站,并使用Alice的详细信息登录,开始浏览。
    • Alice tries to continue browsing, is locked out, has to log in again. Alice试图继续浏览,被锁定,必须再次登录。
    • Bob is now locked out. 鲍勃现在被锁定了。
    • etc. 等等

At its most basic, this won't stop the users sharing their logins, but will cause them annoyance, forcing them to keep logging in. If you need to you can add a delay to the login process - so if a different session id attempts to log into the site within the session time-out (defaults to 20 minutes) or some other time, say based on the average time a user spends on a page, then deny the login attempt. 最基本的,这不会阻止用户共享他们的登录,但会导致他们烦恼,迫使他们继续登录。如果需要,可以为登录过程添加延迟 - 所以如果尝试不同的会话ID在会话超时(默认为20分钟)或其他时间(例如,基于用户在页面上花费的平均时间)登录站点,然后拒绝登录尝试。

There could be several possibilities. 可能有几种可能性。 A quick response is: 快速回复是:

  1. Maintain a flag in database; 在数据库中保持一个标志; upon every login/out update the flag. 每次登录/退出时都会更新标志。 For instance, upon every authentication request you can reject the login request if the flag is already true. 例如,如果标志已经为真,则每次认证请求都可以拒绝登录请求。

  2. Alternatively, you can maintain a list of users in the Application object and use .Contains to see if it already exists. 或者,您可以在Application对象中维护用户列表,并使用.Contains查看它是否已存在。

--EDIT-- - 编辑 -

Lets try the database flag option; 让我们尝试数据库标志选项; and assume that you have a method called StillLoggedIn(User) that updates the date/time and flag. 并假设您有一个名为StillLoggedIn(User)的方法来更新日期/时间和标志。

So, when user logs in: 因此,当用户登录时:

  1. The app is going to authenticate the user and set flag=1, and mark a date/time stamp. 该应用程序将验证用户并设置flag = 1,并标记日期/时间戳。
  2. For subsequent requests, the app would call StillLoggedIn(User) ; 对于后续请求,应用程序将调用StillLoggedIn(User) ;

  3. Prepare a windows service that would browse the database from time to time(lets say after 5 minutes if you have 10000 users). 准备一个不时浏览数据库的Windows服务(如果你有10000个用户,可以说5分钟后)。 The service would compare the database date/time with the current date/time and mark the flag as 0 if the currentTime minus lastUsedTime is greater than, lets say, 5 minutes . 该服务将数据库日期/时间与当前日期/时间进行比较,如果currentTime减去lastUsedTime大于5分钟,则将该标志标记为0

It could be anything besides a database and windows service. 它可以是数据库和Windows服务之外的任何东西。

What we did is we used a combination of Session state and Application state to prevent duplicate login. 我们所做的是使用Session状态和Application状态的组合来防止重复登录。

When a user logs-in his userId is retrieved from the asp.net membership database and saved in the Application state as a unique object. 当用户登录时,他的userId从asp.net成员资格数据库中检索并作为唯一对象保存在Application状态中。

Since Application state is global to the application and not specific to a user session, we can check whether the userId is already saved in Application state. 由于Application状态对应用程序是全局的而不是特定于用户会话,因此我们可以检查userId是否已经保存在Application状态。 If it is already saved we can notify the user and stop the login. 如果已经保存,我们可以通知用户并停止登录。 When the session expires (on Session_End within the Global.asax file), that Application state object for that particular user can be removed from Application state so that he can log in again after his session has expired. 当会话到期时(在Global.asax文件中的Session_End上),可以从应用程序状态中删除该特定用户的该应用程序状态对象,以便他可以在其会话到期后再次登录。

Here's the code: In Login.aspx.cs: 这是代码:在Login.aspx.cs中:

protected void OnLoggingIn(object sender, LoginCancelEventArgs e)
    {
        // Accesses the database to get the logged-in user.
        MembershipUser userInfo = Membership.GetUser(LoginUser.UserName);
        UserMan.UserID = userInfo.ProviderUserKey.ToString();

        if (Application[UserMan.UserID] != null)
        {
            if (Convert.ToString(Application[UserMan.UserID]) == UserMan.UserID)
            {
                e.Cancel = true;
            }
            else
            {
                // Save the user id retrieved from membership database to application state.
                Application[UserMan.UserID] = UserMan.UserID;
            }
        }
        else
        {
            Application[UserMan.UserID] = UserMan.UserID;                
        }
    }

And in Global.asax: 在Global.asax中:

void Session_End(object sender, EventArgs e)
    {
        // Code that runs when a session ends. 
        // Note: The Session_End event is raised only when the sessionstate mode
        // is set to InProc in the Web.config file. If session mode is set to StateServer 
        // or SQLServer, the event is not raised.

        if (Application[UserMan.UserID] != null)
        {
            if (Convert.ToString(Application[UserMan.UserID]) == UserMan.UserID)
            {                    
                Application.Contents.Remove(UserMan.UserID);
            }
        }
    }

Although this solution seems a little messy, it works quite well without too much coding and fewer database hits. 虽然这个解决方案看起来有点乱,但它没有太多的编码和更少的数据库命中,效果很好。

This is the way i do. 这就是我的方式。

Once user login, check the flag and sessionID from DB, If found logged in with same account and different sessionID(Compare newly generated current sessionID and sessionID from DB), alert user something like "System detected you did not log out from your last login, Click<"OK"> to log out last login and create new session." 用户登录后,检查来自DB的flag和sessionID,如果发现使用相同的帐户和不同的sessionID登录(比较新生成的当前sessionID和来自DB的sessionID),请提醒用户“系统检测到您没有从上次登录时退出,单击<“确定”>以注销上次登录并创建新会话。“ If OK, just replace the old SessionId with current SessionID in DB. 如果正常,只需将旧的SessionId替换为DB中的当前SessionID。

One more thing is to check current sessionID and sessionID from DB in everypage, if it not same, logout and redirect to login page. 还有一件事是在每个页面中检查来自DB的当前sessionID和sessionID,如果不相同,则注销并重定向到登录页面。

No matter user did not logout properly or just close browser, user has chance to logout theirself and no need to wait until session end from IIS. 无论用户没有正确注销或只是关闭浏览器,用户都有机会注销自己,无需等到IIS会话结束。 It will prevent multiple login with same account at the same time. 它将阻止同时使用同一帐户进行多次登录。

Hope this help, thanks... 希望这有帮助,谢谢......

There is no one answer here as it depends on how you are authenticating users. 这里没有一个答案,因为它取决于您如何验证用户。 However, the basic logic would be simple - when a user logs in, checked their username or ID against a list of already logged in users and, if there is a match, do not authenticate them (and instead give them some kind of message explaining why they cannot log in). 但是,基本逻辑很简单 - 当用户登录时,根据已登录用户的列表检查其用户名或ID,如果匹配,则不对其进行身份验证(而是给他们某种消息解释)为什么他们无法登录)。

Obviously the exact way you do this depends on how you are authenticating users and storing user details - you will need to supply more details if you want more help. 显然,您执行此操作的确切方式取决于您对用户进行身份验证以及存储用户详细信息的方式 - 如果您需要更多帮助,则需要提供更多详细信息。

I looked at the membership table and didnt see any column like "IsLoggedIn" so membership API does not meet this requirement. 我查看了成员资格表并没有看到像“IsLoggedIn”这样的列,因此成员资格API不符合此要求。

May be you can use Asp.net Cache system and flag user as "LoggedIn". 可能是您可以使用Asp.net Cache系统并将用户标记为“LoggedIn”。 With this way you can check for extra logins. 通过这种方式,您可以检查额外的登录。

Zhaph - Ben Duguid,Little note Profile无法在AuthenticateRequest中访问,因为它不会在AcquireSessionState应用程序事件之前创建,所以如果他们使用这种方法(而不是页面方法)他们必须处理AcquireRequestState或PostAcquireRequestState

When member loged in. setup a Random int ex. 当成员进入时。设置一个Random int ex。 randNo, save cache[UserName]=randNo, session[UserName]=randNo. randNo,保存缓存[UserName] = randNo,session [UserName] = randNo。 When member access any page we check: cache[UserName]==Session[UserName] is ok, else this user will be Log Out. 当成员访问我们检查的任何页面时:cache [UserName] == Session [UserName]没问题,否则该用户将登出。 (Mean: login first, logout first) (意思是:先登录,先退出)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何防止使用缓存在asp.net中从同一用户ID登录多个用户? - How to prevent multiple user login from the same user id in asp.net using cache? OWIN ASP.NET - 避免在Web Api中没有Identity的同一帐户进行多次登录 - OWIN ASP.NET - Avoid multiple logins for the same account without Identity in Web Api 当同一用户ID尝试登录多台设备时,如何杀死另一台设备上的会话? Asp.net身份 - When the same user ID is trying to log in on multiple devices, how do I kill the session on the other device? Asp.net Identity ASP.NET MVC Forms身份验证多个同时登录 - ASP.NET MVC Forms Authentication multiple simultaneous logins 注销并多次登录时的ASP.net计时器 - ASP.net timer when logged out and multiple logins 是否可以在同一个ASP.NET应用程序中进行常规登录和ActiveDirectory登录? - Is it possible to have regular logins and ActiveDirectory logins in the same ASP.NET app? asp.net:如何防止用户多次发布相同的数据 - asp.net: how do i prevent users from posting the same data multiple times 如何通过ASP.NET网站上的ID限制网站/链接访问? - How to restrict website / link access by ID on ASP.NET site? Asp.net FindControl +“具有相同ID的多个控件” - Asp.net FindControl + “Multiple controls with the same ID” asp.net多用户控制客户端ID问题 - asp.net multiple user control client id issue
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM