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

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

问题描述

我正在使用带有Richfaces和Facelets的JSF 1.2。

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?

推荐答案

独立于数据库的方法是让用户有一个静态Map< User,HttpSession> 变量并实现 了HttpSessionBindingListener (和 Object#equals() Object#hashCode() )。这样你的webapp仍会在意外崩溃后仍然运行,这可能导致数据库值不会更新(你当然可以创建一个 ServletContextListener ,它会重置webapp上的数据库启动,但这只是越来越多的工作)。

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).

以下是用户的外观:

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 = userDAO.find(username, password);
if (user != null) {
    sessionMap.put("user", user);
} else {
    // Show error.
}

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

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

当您注销用户时,如下所示:

When you logout the User as follows:

sessionMap.remove("user");

或当会话超时时, valueUnbound(),将用户从登录地图中删除。

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

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

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