2008-09-25 30 views
8

几年前,我开发了一个Web应用程序,我们希望确保用户不共享凭据。如何确保用户只登录一次?

我们决定要做的事情之一是只允许用户一次从一台计算机登录。我这样做的方式是每隔N秒就有一个iframe对服务器进行ping操作;只要服务器有特定用户(来自特定IP)的心跳,该用户就不能从任何其他IP登录。

该解决方案虽然得到了我的管理员的认可,但对我来说却总是显得有些尴尬。此外,它似乎很容易规避。

有没有一种确保网络应用程序用户只登录一次的好方法?说实话,我从来不明白为什么管理层甚至想要这个功能。在分布式应用程序上执行此操作是否有意义?

+0

你有没有遇到客户IP变化的问题?或者是你的环境避免了这个问题? – Owen 2008-09-25 23:31:19

+0

我们在IP变化方面没有问题。这是我们控制IP地址的CSR的应用程序。 – 2008-09-25 23:35:39

回答

11

我通过维护当前登录用户的散列表实现了这一点,关键是用户名,值是他们的最后一次活动时间。

登录时,您只需检查该密钥的哈希表,如果存在,则拒绝登录。

当用户执行任何操作时,用时间更新散列表(如果将其作为核心页框架的一部分,这很容易)。

如果散列表中的时间大于20分钟的非活动时间,则将其删除。每次检查hashtable时都可以这样做,所以即使你只有一个用户,并且在几个小时后尝试登录,在初始检查期间,它也会将它们从哈希表中移除以便闲置。

在C#(未测试)的一些例子:

public Dictionary<String,DateTime> UserDictionary 
{ 
    get 
    { 
     if (HttpContext.Current.Cache["UserDictionary"] != null) 
     { 
      return HttpContext.Current.Cache["UserDictionary"] as Dictionary<String,DateTime>; 
     } 
     return new Dictionary<String,DateTime>(); 
    } 
    set 
    { 
     HttpContext.Current.Cache["UserDictionary"] = value; 
    } 
} 

public bool IsUserAlreadyLoggedIn(string userName) 
{ 
    removeIdleUsers(); 
    return UserDictionary.ContainsKey(userName); 
} 

public void UpdateUser(string userName) 
{ 
    UserDictionary[userName] = DateTime.Now; 

    removeIdleUsers(); 
} 

private void removeIdleUsers() 
{ 
    for (int i = 0; i < UserDictionary.Length; i++) 
     { 
      if (user[i].Value < DateTime.Now.AddMinutes(-20)) 
       user.RemoveAt(i); 
     } 
} 
1

在高度安全的应用程序中,您可能需要这样做。你可以做的是保持登录计数递增,登录用户和IP地址。计数不应该是2.如果是,那么你将其他IP记录下来,无论它登录到哪个IP都被抛出。这不会阻止用户1向用户2提供他的凭据,如果用户2同时在其他地方登录,那么只会让用户1做他的工作令人沮丧。

1

我从来没有找到这个问题的标准解决方案。在我的一个应用程序中,我使用了Javascript + Java的组合来确保用户只能从指定的IP(实际上它是一个会话ID)只记录一次,但在最坏的情况下,超时(设置为2分钟)该帐户不可用。 我不这样做,为什么没有一个共同的方式来做到这一点。

3

看着眼前IP是不可靠的。 IIRC有一些代理类型可以在多个IP地址上随机地发送传出请求。根据您的应用程序的范围,这可能会影响您,也可能不会影响您。其他代理将显示来自单个IP的大量流量。

上次登录时间也是一个问题。考虑基于cookie的认证,其中认证cookie不持久(一件好事)。如果浏览器崩溃或关闭,则用户必须重新登录,但不能超时。如果该应用程序用于交易股票,那么20分钟不工作就会花钱,并且可能无法接受。

通常可以购买智能防火墙/路由器,这些智能防火墙/路由器比您或我可以做的一次性做得更好。它们还有助于防止重播攻击,cookie窃取等,并且可以配置为与您选择的Web平台中的标准机制一起运行。

1

我刚刚有这个问题。

我们要建立一个包含Flex应用程序(客户端内置)Drupal站点,他希望以下内容:

  1. 透明登录由Drupal的< - > FLEX(!的Bleh)
  2. 没有并发登录!

他测试的废话了每一个解决方案,并在年底,这就是我们所做的:

  • 我们沿途经过的每个URL的会话ID通过。
  • 当用户登录时,我们建立了一个时间戳IP-SessionID-用户名足迹
  • 每一页,数据库都被ping通了,如果同一个用户被发现在同一个IP上有不同的SessionID,他们旧的用户被引导

该解决方案满足了我们客户的严格测试(在他house..he 2台电脑使我们了寻找小小时角落和缝隙中的代码之前,我们来到了这个解决方案)

4

我会绕过这个问题,并允许上次登录的代价是任何以前的登录,所以无论何时用户登录,终止任何其他呃他可能有的登录会话。

这是它实施的很多eaiser,你最终知道你在哪里。

4

在这样一个'功能'上被警告 - 这是一个边缘案例的大象陷阱,你最终以为你钉了它,然后你或别人说“但是如果有人做了X?你意识到你必须添加另一层复杂性。

例如:

  • 如果哪一个用户打开的会话的复制一个新的标签?
  • 如果用户打开新的浏览器窗口,该怎么办?
  • 如果用户登录并且浏览器崩溃,该怎么办?

等等...

基本上有一系列或多或少哈克的解决方案没有的这些都是万无一失,所有这些都将是难以维持和。通常客户的真正目标是其他一些合法的安全目标,例如“阻止用户共享帐户”。

最好的想法是找出潜在的目标是什么,并找到一个满足这个目标的方法。我恐怕涉及谈判外交和其他这样的“软技能”,而不是走上技术性的大雁追逐..,