当他使用相同的凭据登录两次时如何使用户会话无效 [英] How to invalidate an user session when he logs twice with the same credentials

查看:20
本文介绍了当他使用相同的凭据登录两次时如何使用户会话无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将 JSF 1.2 与 Richfaces 和 Facelets 结合使用.

I'm using JSF 1.2 with Richfaces and Facelets.

我有一个包含许多会话范围 bean 和一些应用程序 bean 的应用程序.

I have an application with many session-scoped beans and some application beans.

用户使用 Firefox 登录.创建一个 ID="A" 的会话;然后他打开 Chrome 并使用相同的凭据再次登录.创建了 ID="B" 的会话.

The user logs in with, let's say, Firefox. A session is created with ID="A"; Then he opens Chrome and logs in again with the same credentials. A session is created with ID="B".

创建会话B"后,我希望能够销毁会话A".怎么做?

When the session "B" is created, I want to be able to destroy session "A". How to do that?

还有.当 Firefox 中的用户执行任何操作时,我希望能够显示一个弹出窗口或某种通知,说您已被注销,因为您已从其他地方登录".

Also. when the user in Firefox does anything, I want to be able to display a popup or some kind of notification saying "You have been logged out because you have logged in from somewhere else".

我有一个 sessionListener 来跟踪创建和销毁的会话.问题是,我可以将 HTTPSession 对象保存在应用程序范围的 bean 中,并在检测到用户已登录两次时销毁它.但是有些东西告诉我这是错误的,并且行不通.

I have a sessionListener who keeps track of the sessions created and destroyed. The thing is, I could save the HTTPSession object in a application-scoped bean and destroy it when I detect that the user has logged in twice. But something tells me that is just wrong and won't work.

JSF 是否在服务器端的某处跟踪会话?如何通过标识符访问它们?如果不是,如何踢掉用户两次登录的第一次登录?

Does JSF keep track of the sessions somewhere on the server side? How to access them by identifier? If not, how to kick out the first log in of an user when he logs in twice?

推荐答案

DB-independent 方法是让 User 有一个 static Map 变量并实现 HttpSessionBindingListener(和 Object#equals()Object#hashCode()).这样,您的 web 应用程序在意外崩溃后仍将运行,这可能导致 DB 值未更新(您当然可以创建一个 ServletContextListener 在 webapp 启动时重置 DB,但仅此而已以及更多工作).

The DB-independent approach would be to let the User have a static Map<User, HttpSession> variable and implement HttpSessionBindingListener (and Object#equals() and Object#hashCode()). This way your webapp will still function after an unforeseen crash which may cause that the DB values don't get updated (you can of course create a ServletContextListener which resets the DB on webapp startup, but that's only more and more work).

User 应如下所示:

public class User implements HttpSessionBindingListener {

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

    // 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);
    }

}

当您登录User如下:

User user = userDAO.find(username, password);
if (user != null) {
    sessionMap.put("user", user);
} else {
    // Show error.
}

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

then it will invoke the valueBound() which will remove any previously logged in user from the logins map and invalidate the session.

当您按如下方式注销 User 时:

When you logout the User as follows:

sessionMap.remove("user");

或者当会话超时时,将调用 valueUnbound() 将用户从 logins 映射中删除.

or when the session is timed out, then the valueUnbound() will be invoked which removes the user from the logins map.

这篇关于当他使用相同的凭据登录两次时如何使用户会话无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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