阻止多个用户登录 - HttpSessionBindingListener

时间:2015-03-30 17:36:03

标签: java servlets login

我有一个Web应用程序,我想阻止用户多次登录(来自同一台机器或不同机器上的不同浏览器)。

我读到了HttpSessionBindingListener,我尝试调整我的登录servlet和用户Bean来实现所需的解决方案。不幸的是,只有当我第二次在同一个浏览器上登录时(在不同的选项卡中),它才有效,但是如果我更换浏览器(在同一台机器上),它就不再起作用了。

代码如下。

用户Bean在成功登录后进入会话

public class BeanUtente implements HttpSessionBindingListener {

private String username;
private String gruppo;

public boolean ruoloPresente(String nomeRuolo) {
    //se il gruppo dell'utente è uguale a quello richiesto dal filtro
    if (this.gruppo.equals(nomeRuolo))
        return true;
    else
        return false;
}

public void valueBound(HttpSessionBindingEvent argo) {
    System.out.println("Value Bound Called, " + argo.getValue() + " isNewSession: " + argo.getSession().isNew());
}

public void valueUnbound(HttpSessionBindingEvent argo) {
    System.out.println("Value UnBound Called, " + argo.getValue() + " isNewSession: " + argo.getSession().isNew());
}

public String toString() {
    return "Username is: " + username;
}

public String getUsername() {
    return username;
}

public void setUsername(String username) {
    this.username = username;
}

public String getGruppo() {
    return gruppo;
}

public void setGruppo(String gruppo) {
    this.gruppo = gruppo;
}

}

登录servlet

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    Db db = null;
    PreparedStatement ps = null;
    ResultSet rs = null;

    try {
        response.setHeader("Cache-Control","no-cache,no-store,must-revalidate");
        response.setHeader("Pragma","no-cache");
        response.setDateHeader("Expires", 0);

        Locale locale = request.getLocale();
        ResourceBundle labels = ResourceBundle.getBundle("risorse.label", locale);

        String urlLoginOk = getInitParameter("urlLoginOk");
        String urlLoginKo = getInitParameter("urlLoginKo");

        String username = request.getParameter("username");
        String password = request.getParameter("password");

        db = new Db();
        db.apriConnessione();

        String sql = "SELECT gruppo FROM Utenti WHERE username=? AND password=SHA2(?, 512)";

        ps = db.getConnection().prepareStatement(sql);
        ps.setString(1, username);
        ps.setString(2, password);
        rs = ps.executeQuery();

        //login OK
        if(username != null && password != null && rs.next()) {
            BeanUtente beanUtente = new BeanUtente();
            beanUtente.setUsername(username);
            beanUtente.setGruppo(rs.getString("gruppo"));

            HttpSession sess = request.getSession();
            sess.setAttribute("beanUtente", beanUtente);

            request.getRequestDispatcher(urlLoginOk).forward(request, response);
        }
        //login KO
        else {
            request.setAttribute("errore", labels.getString("loginFallito"));
            request.getRequestDispatcher(urlLoginKo).forward(request, response);
        }

    }
    catch(Exception e) {
        e.printStackTrace();
    }
    finally {
        try {
            if(!ps.isClosed())
                ps.close();
            if(!rs.isClosed())
                rs.close();
        }
        catch (SQLException sqle) {
            sqle.printStackTrace();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if(db.getConnection() != null)
                db.chiudiConnessione();
        }
    }

}

这是日志。 当我第一次登录时,我得到:

*Value Bound Called, Username is: pi isNewSession: false*

当我第二次从同一个浏览器登录时,我得到:

*Value Bound Called, Username is: pi isNewSession: false
Value UnBound Called, null isNewSession: false*

所以似乎正确调用了UnBound方法。 但是,如果我第三次从同一台机器上的另一个浏览器登录,我会得到:

*Value Bound Called, Username is: pi isNewSession: false*

即,尚未调用UnBound方法。

你能帮助我理解我的错误在哪里吗? 我想我必须明确调用session.removeAttribute(“beanUtente”)但是何时/在哪里?

提前感谢您的任何帮助:)

2 个答案:

答案 0 :(得分:0)

为避免从多个浏览器登录,我不认为HttpSessionBindingListener会起作用,因为使用新浏览器,它会创建新会话。

您必须在特定用户的后端保存状态,对每个用户说userId,登录后可能在cache/DB,并从{{1}中删除一旦他退出,

所以当用户登录时如下所示。 Object user = getUser(userId);

if(user!= null){   //用户已登录,只返回自定义消息 } 其他{   //允许用户登录 }

cache/DB上的logoutuserId移除cache/user

答案 1 :(得分:0)

    @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests()
                    .mvcMatchers("/").permitAll()
                    .and().sessionManagement()
                    .maximumSessions(1);

        }