会话处理问题(更新数据库行) - 会话随浏览器一起关闭

时间:2013-02-13 09:44:44

标签: java jsp session servlets session-timeout

我使用数据库存储用户详细信息,包括用户名和密码。它还有一个Security_check列,默认情况下为“logged_out”。

每当用户登录时,我都会从我验证用户(servlet)的页面将Security_check值修改为“logged_in”。每当用户点击退出按钮时,我都会明确地将Security_check更改为其默认值。

但是当用户关闭浏览器而没有注销时,则存在一个很大的问题,因为该用户的Security_check列值仍然是“logged_in”,之后当该用户厌倦登录时,他们将收到一条错误消息,指出您已经登录(因为我在允许任何用户登录之前检查Security_check,并且在这种情况下他们已经登录)。所以他无法登录,也无法注销,因为当他关闭浏览器时会话已过期。那我该怎么办?

以下是HttpSessionListener类的代码,该代码无效:

package com.svc.session;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.sql.*;
import javax.servlet.http.HttpSession;


public class Session_Invalidator implements HttpSessionListener
{
    public Session_Invalidator()
    {
        try    
        {
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        }
        catch(Exception e) 
        {
        }
    }

    public void sessionCreated(HttpSessionEvent se)
    {
    }

    public void sessionDestroyed(HttpSessionEvent se)    
    {
        HttpSession session = se.getSession();
        String uName = session.getAttribute("userName").toString().trim();

        Connection con = null;
        PreparedStatement stmt = null;

        try 
        {
            // i am using a space between the colon and odbc because if 
            // I don't it will be converted to smile, so ignore the space
            con = DriverManager.getConnection("jdbc: odbc:CMS","","");
            stmt = con.prepareStatement("update Users set security_check=default where     login_name=?");
            stmt.setString(1, uName);
            int no = stmt.executeUpdate();
        } catch(Exception e) 
        {
        }
    }
}

2 个答案:

答案 0 :(得分:1)

它认为你有两种选择。

  1. 选择一个非常短的会话超时(比如一两分钟),并通过AJAX调用实现从网页到服务器的ping操作。因此,当用户浏览器打开并显示您的网页时,您的服务器将始终收到ping通知并保持会话打开状态。如果用户关闭浏览器,您的服务器会话很快就会超时。但仍有短暂的延迟。这种方法的缺点是您将产生更多流量,并且您必须找到适当的会话超时值。如果存在一些网络延迟,则太短的值可能导致会话超时。太长的值会增加用户无法重新登录的时间段。

  2. 这是我最喜欢的解决方案:不要过于严格禁止重新登录。不要将登录状态存储在数据库中。如果用户想要在关闭浏览器后重新登录,则会创建一个新的服务器端会话,并且用户会提供登录凭据,而且好的是。旧会话将在超时后销毁。如果您使用基于容器的安全性,这是默认行为。我建议使用基于容器的安全性(JAAS)。为什么要禁止重新登录?

  3. 以下是有关JAAS的一些链接:

答案 1 :(得分:1)

我有一个解决这个问题的解决方法,就是使用全局对象将sessionId和用户的id存储在一起,当会话超时时,我们可以从会话销毁事件中获取sessionId,然后我们可以通过sessionId获取用户的id。 请查看我的博客:Update DB's User status when Session timeout