使用相同的用户名和密码防止多次登录

viv*_*mal 15 java servlets

我正在开发一个应用程序,需要使用相同的用户名和密码来防止多次登录.

如果它发生在同一台机器上,那么显然我们需要对用户会话做一些事情,但是如果它们使用相同的用户名和密码登录到不同的机器上,它也应该防止.

我们必须牢记以下事项:

  1. 如果用户关闭浏览器而不注销.
  2. 如果会话超时.

我将不胜感激任何帮助.

Bal*_*usC 25

如果用户关闭浏览器而不注销.

特别是这种情况很难并且检测不可靠.您可以使用beforeunload在Javascript中的事件,但你完全依赖于浏览器是否已启用JS和特定的浏览器支持这种非标准的事件(如Opera没有).这也是我建议只注销以前登录用户而不是阻止登录的主要原因之一.这也更人性化,安全的用户"忘记"从其他计算机注销的情况.

最简单的办法就是让User有一个static Map<User, HttpSession>变量,让它实现HttpSessionBindingListener(和Object#equals()Object#hashCode()).

public class User implements HttpSessionBindingListener {

    // All logins.
    private static Map<User, HttpSession> logins = new HashMap<User, HttpSession>();

    // Normal properties.
    private Long id;
    private String username;
    // Etc.. Of course with public getters+setters.

    @Override
    public boolean equals(Object other) {
        return (other instanceof User) && (id != null) ? id.equals(((User) other).id) : (other == this);
    }

    @Override
    public int hashCode() {
        return (id != null) ? (this.getClass().hashCode() + id.hashCode()) : super.hashCode();
    }

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        HttpSession session = logins.remove(this);
        if (session != null) {
            session.invalidate();
        }
        logins.put(this, event.getSession());
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        logins.remove(this);
    }

}
Run Code Online (Sandbox Code Playgroud)

当您登录时User如下:

User user = userDAO.find(username, password);
if (user != null) {
    request.getSession.setAttribute("user", user);
} else {
    // Show error.
}
Run Code Online (Sandbox Code Playgroud)

然后它将调用valueBound()将从logins地图中删除任何先前登录的用户并使会话无效.

当您注销时User如下:

request.getSession().removeAttribute("user");
Run Code Online (Sandbox Code Playgroud)

或者当会话超时时,valueUnbound()将调用将logins地图中的用户删除.


小智 5

在数据库中创建一个表 - 让我们调用它[online_users]- 包含三个字段:

[online_users]
1. username
2. login_time
3. logout_time
Run Code Online (Sandbox Code Playgroud)

每当用户登录时,请插入用户名和登录时间[online_users].

在要求用户登录的所有页面上,放置此条件:检查[online_users]用户是否logout_time为空.

每当用户按下注销按钮时,为该用户的名称设置logout_timein [online_users].

如果有人试图用积极的用户名和密码登录,检查usernamelogout_time,并显示一条消息,说明用户已经登录.而且,最重要的是,设置logout_timeMULTIPLELOGIN该用户.

如果该用户在任何其他计算机上登录,那么如果他刷新或导航到另一个页面,该站点将告诉他他已经注销.然后,可以将用户重定向到站点的主页.


Sha*_*pta 3

在表中取一个额外的字段,列名称为“IsLoggedIn”作为位字段,并将其设置为 true,直到用户登录。用户注销后,立即将其设置为 false。这也需要在会话到期时间完成。一旦会话过期,该字段应使用触发器或通过 SP 调用自动设置为 false

好的解决方案仍然受到欢迎