本帖最后由 darkhorse001 于 2009-07-23 13:58:18 编辑

解决方案 »

  1.   

    我只知道有个 单点登录, 怎么操作就不清楚了,其实可以考虑在数据库中加一个字段, 登录前要看这个值是否是已经登录的标识, 如果不是,登录成功后就将其设为已经登录,否则,就返回 false,不给登录 
      

  2.   

    假如你数据库可以改的话,在数据库添加一个状态,
    假如不能改的话:
     如果是Session就去判断Session是不是new
     如果是Cokie的话就在Bean里添加一个状态值,用户监视当前用户状态
      

  3.   

    sql for update---行记录锁死。退出开锁。更新最后登陆时间字段。
      

  4.   

    单点登录这个问题很难解决的。如果在数据库中加字段进行区别,那么如楼上所说,用户非法退出怎么处理;如果是在session或者是Cokie的话那么在不同的机器上用一个用户名登录又该怎么处理等等,我目前也在考虑这个问题,不过还没有找到好的处理方法。
      

  5.   

    session监听器      。
      

  6.   

    package com.jzaccp.oa.grbg.sessionlistener; import javax.servlet.http.*; 
    import javax.servlet.*; 
    import java.util.*; public class onLineUser implements HttpSessionBindingListener { 
        public onLineUser(){ 
      }   private Vector users=new Vector(); 
      /** 
        * 获取在线人数 
        * @return 
        */ 
      public int getCount(){ 
            users.trimToSize(); 
          return users.capacity(); 
      } 
      /** 
        * 判断用户是否存在 
        * @param userName 
        * @return 
        */ 
      public boolean existUser(String userName){    
      users.trimToSize(); 
          boolean existUser=false; 
          for (int i=0;i <users.capacity();i++ ) 
          { 
              if (userName.equals((String)users.get(i))) 
              { 
                  existUser=true; 
                  break; 
              } 
          } 
          return existUser; 
      } 
    /** 
    * 删除用户 
    * @param userName 
    * @return 
    */ 
      public boolean deleteUser(String userName) { 
          users.trimToSize(); 
          if(existUser(userName)){ 
              int currUserIndex=-1; 
              for(int i=0;i <users.capacity();i++){ 
                  if(userName.equals((String)users.get(i))){ 
                      currUserIndex=i; 
                      break; 
                  } 
              } 
              if (currUserIndex!=-1){ 
                  users.remove(currUserIndex); 
                  users.trimToSize(); 
                  return true; 
              } 
          } 
          return false; 
      } 
    /** 
    * 得到用户的列表 
    */ 
      public Vector getOnLineUser() 
      { 
          return users; 
      } 
      /** 
        * 植入session时调用的方法 
        * 
        */ 
        public void valueBound(HttpSessionBindingEvent e) { 
          users.trimToSize(); 
          if(!existUser(e.getName())){ 
              users.add(e.getName()); 
              System.out.print(e.getName()+"\t  登入到系统\t"+(new Date())); 
              System.out.println("      在线用户数为:"+getCount()); 
          }else 
              System.out.println(e.getName()+"已经存在"); 
        } 
    /** 

    * session过期或被关闭或退出调用的方法 
    */ 
        public void valueUnbound(HttpSessionBindingEvent e) { 
            users.trimToSize(); 
            String userName=e.getName(); 
            deleteUser(userName); 
            System.out.print(userName+"\t  退出系统\t"+(new Date())); 
            System.out.println("      在线用户数为:"+getCount()); 
          } } 
      

  7.   

    package Servlet;
    import javax.servlet.http.HttpSessionAttributeListener;
    import javax.servlet.http.HttpSessionBindingEvent;
    import javax.servlet.http.*;
    import java.util.*;public class SessionListener  implements HttpSessionListener
    {
    private static HashMap hUserName = new HashMap();//保存sessionID和username的映射
        /**以下是实现HttpSessionListener中的方法**/
        public void sessionCreated(HttpSessionEvent se){
        }
        
        public void sessionDestroyed(HttpSessionEvent se){
            hUserName.remove( se.getSession().getId() );
        }
        /*
         * isAlreadyEnter-用于判断用户是否已经登录以及相应的处理方法
         * @param sUserName String-登录的用户名称
         * @return boolean-该用户是否已经登录过的标志
         */
        public static boolean isAlreadyEnter(HttpSession session,String sUserName){
            boolean flag = false;
            if(hUserName.containsValue(sUserName)){//如果该用户已经登录过,则使上次登录的用户掉线(依据使用户名是否在hUserName中)
                flag = true;
                int i=0;
                //遍历原来的hUserName,删除原用户名对应的sessionID(即删除原来的sessionID和username)
                Iterator iter = hUserName.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry)iter.next();
                    Object key = entry.getKey();
                    Object val = entry.getValue();
                    i++;
                    if( ( (String)val ).equals(sUserName) ){
                        hUserName.remove(key);
                    }
                }
                session.setAttribute("ii", i);
                hUserName.put( session.getId(),sUserName );//添加现在的sessionID和username
                System.out.println("hUserName = " + hUserName);
            }
            else{//如果该用户没登录过,直接添加现在的sessionID和username
                flag = false;
                hUserName.put( session.getId(),sUserName );
                System.out.println("hUserName = " + hUserName);
            }
            return flag;
        }
      

  8.   

    纯理论,没有实践过!
    1,不要完全靠session来控制,session会有一个失效时间,这个时间不宜设的太短,否则正常工作会受影响。用监听事件的方法也是不可取的,事实上这个事件也会等到session过期的时候才会触发。
    2,可以采用隐藏桢的方式来检测用户的在线,这个时间可以设的比较短。比如5分钟。就像dev-club.com一样。在这个桢里得到用户名,当时的IP,以及访问时间。记录在application中。
    3,当另有用户来访问的时候,就判断在application的数据,如果已经有该用户的访问记录,就按IP和时间来判断,是否可以继续。比如说IP不同,但时间隔了很久了,就允许访问。
    4,你还可以再写一个后台进程来对application中的过期数据进行清理。
    5,对于使用代理或网关访问的用户判断可以这样,session对象有一个方法叫getId(),可以得到一个唯一的ID。即使使用同一IP来访问,这个ID也是不同的,可以加以区分。
      

  9.   

    给你说一下我用过的方法:
    1.在用户表里加一个字段,sessionid,在用户登录时创建的session的id值存入数据库,只需要在用户登录时修改这个值
    2.用一个过滤器,当用户请求过来时,检验一下当前请求的sessionid跟数据库中的是否一致,不一致则跳转到登录页面这个方法是不在登录时限制,而是把之前登录的用户踢下线,所以不存在意外登出时无法改变登录状态的情况,代价就是每个请求要比较一下sessionid,看你如何取舍了!仅供参考
      

  10.   

    监听器是可以 自动修改字段。。那很吊滴第一种情况      你可以在他关闭窗体滴时候去  修改数据库字段
    第二种情况就是         他直接把电源关掉(session监听30分钟用户没操作 ,就自动修改掉用户的状态)
    不过存在30分钟误差  ,,我也不知道怎么去掉。。//测试时间短一点
    session.setMaxInactiveInterval(12);// Sesion有效时长,以秒为单位
      

  11.   

    我现在能想到的就是给工程加一个HttpSessionListener监听,但是这样做也不是很好,要是用户非正常退出,在session没过期前就登陆不进去了!
      

  12.   


    http://topic.csdn.net/u/20081228/16/c89e1726-ec81-4a96-9bdf-478383578896.htmlhttp://mywork.javaeye.com/blog/66069
      

  13.   

    配个过滤器    路径设置 为/* 检查sessionId 的直 如果为null 则强行退出或者给提示 不停比对 1 个 登陆先恢复数据库sessionid  null状态  再插入自己的  2在登陆时恢复默认值null 同时 也就相当于把1提下 去了 有点麻烦  没找到更好的  有别忘记告诉下啊 
      

  14.   

      利用数据库中添加一字段来判断,是有漏洞的,假如用户非法退出,你的字段标识就改不回去了,下次就无法登陆了,上面有说可以捕获关闭事件,那么我问,如果我用任务管理器强制结束任务呢或者突然机器死掉了呢,类似的现象多了。
       通过实践,我觉得可以用“踢人策略”,也就是最后一个登陆的主动剔除上一登陆者。具体做法如下:
       在用户登陆的时候,把用户的帐号当Key,把产生的sessionID当value保存到全局变量中servletContext.setAttribute(userid,session.getId());  
       然后配置过滤器(当每产生一次新的请求时,程序会先经过过滤器),在过滤器中对本次请求的sessionid进行判断(通过帐号获得保存的sesionid),看是否与全局变量中保存的sessionId一致,如果不一致,表明已经有用此帐户做新的一次登陆(每次登陆时会重新保存sessiondi,因为key(帐号)相同,所以value会被替换),那么上一用户将被强制退出(踢出)。
       不给代码,只给正确的思路,这才真正的帮助你,别一提问题,就想要代码,思想是精髓。
      

  15.   

    用一个字段标识  用户是否已登录   然后在用session监视器  监视登录的session状态 来判断用户是否下线
      

  16.   

    用Session + 用户的方式是可以解决的。
    楼主只需要把设计目标改一下,就不用担心用户意外退出的问题了:
    对于同一个用户, 当它登录的时候,判断有没有已经登录的Session存在,如果有,就把先前登录的Session踢掉。
      

  17.   

    想完美的解决,估计很难,加字段还要session监控,意外事件不好把握。
      

  18.   

     使用spring的bean 单例缓存机制就可以实现
     由于springFactroy 在整个服务器中正常情况下是唯一的,所以他的单例模式在一个服务器上也是唯一,
     只要在登录的service上定义一个HashMap  用来保存用户 用户的登录名   , 当用户再次登陆时,
       使用AOP方式,看看HashMap中是否存在着这个用户就可以解决这个问题了。
     如果是多个服务器集成 , 使用Ehcache , 使得服务器的service对象同步
     多个计算机集成,使用通信,使得内存同步
      

  19.   

    监听器,是不够的,最简单的一个列子,在有些操作系统浏览器下,左右frameset的sessionId都会不一样
      

  20.   

    可以用IP绑定 指定的ip可以登录
      

  21.   

    单用户单一登录,如果采用数据库字段纪录,当客户端出现异常,会死锁导致用户不便。而采用Session,如果没有过期,也会导致用户等待。用轮回查询,实在不是很好的方式。个人建议,完全可以采纳后一次登录踢出前一次用户,同时提醒被踢出的的用户。
      

  22.   

    首先每次登陆的时候把信息写入SESSION,然后存入一个静态变量,然后用一个过滤器,每次进入系统的时候判断新SESSION与原来存入变量里面值是否有相同,有相同则清空原有SESSION
      

  23.   

    加一个过滤器,然后像聊天室一样记录一个在线的用户列表及用户的sessionid,
    过滤器里判断是登录,登录了判断用户名是否已经在用户列表里。
      

  24.   

    这个方法不错,可以设定一个Application中数据的有效时间!
      

  25.   

    登录的时候将用户的ID放入Session中,因为用的ID是唯一的,所以当用户重新登录的时候就判断登录的用户的ID和Session 中已经存在的ID是否相同。重复登录的时候是不可以登录成功的。
      

  26.   

    写错了, 是放在Application中方案二。 用户登录后将用户的数据库中的状态改变,退出的时候再改回来。
      

  27.   

    package filter;import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;import vo.UsersInfo;public class SsoFilter implements Filter {
    private static final String PARAM_PWD = "pwd"; // request发来的参数
    private static final String PARAM_UID = "uid";
    private static final String USERS_MAP = "userList"; // application中保存的用户列表
    private static final String USER_INFO = "userInfo"; // session中保存用户时,作键
    private static final String MSG = "msg"; // request中保存提示信息时,作键
    // private static final String MSG_USEING = "该账号正在使用中"; // 提示信息的值
    private static final String MSG_NOTLOGIN = "您尚未登录";
    private static final String MSG_BADLOGIN = "用户名或密码出错";
    private static final String JSP_MAIN = "main.jsp"; // 重定向的页面
    private static final String JSP_LOGIN = "login.jsp"; private HttpServletResponse response = null; // response
    private HttpServletRequest request = null; // request
    private HttpSession session = null; // session
    private ServletContext application = null; // application public void doFilter(ServletRequest arg0, ServletResponse arg1,
    FilterChain arg2) throws IOException, ServletException {
    // 初始化三个参数
    request = (HttpServletRequest) arg0;
    response = (HttpServletResponse) arg1;
    session = request.getSession(); // 1.session已登录,则可以到任何页面
    if (session.getAttribute(USER_INFO) != null) {
    arg2.doFilter(arg0, arg1);
    } else {
    // 2.1尝试登录
    if (request.getRequestURI().indexOf(JSP_MAIN) != -1) {
    tryLogin();
    } else {
    // 2.2尝试越权访问,前往登录页
    request.setAttribute(MSG, MSG_NOTLOGIN);
    request.getRequestDispatcher(JSP_LOGIN).forward(arg0, arg1);
    }
    }
    } /**
     * 尝试登录
     */
    private void tryLogin() throws ServletException, IOException {
    String uid = request.getParameter(PARAM_UID);
    String pwd = request.getParameter(PARAM_PWD); // 直接访问主界面,视为未登录,返回登录页
    if (uid == null || pwd == null || uid.equals("") || pwd.equals("")) {
    request.setAttribute(MSG, MSG_BADLOGIN);
    request.getRequestDispatcher(JSP_LOGIN).forward(request, response);
    return;
    } // 尝试登录
    boolean b = uid.equals(pwd);
    if (b) {
    saveUserVariable(uid);
    request.getRequestDispatcher(JSP_MAIN).forward(request, response);// 登录成功,主界面
    } else {
    request.setAttribute(MSG, MSG_BADLOGIN); // 用户名或密码出错
    request.getRequestDispatcher(JSP_LOGIN).forward(request, response);// 登录失败,登录页
    }
    } // 登录成功,两个步骤
    // 1. session中保存用户身份 [key:USER_INFO, value:u]
    // 2. 更新application中的[在线用户列表]
    @SuppressWarnings("unchecked")
    private void saveUserVariable(String uid) {
    // 1.1
    UsersInfo u = new UsersInfo(request.getRemoteAddr(), 
    uid,
    session.getId());
    session.setAttribute(USER_INFO, u);
    session.setMaxInactiveInterval(9000000); // 1.2
    Map<String, HttpSession> map = application.getAttribute(USERS_MAP) == null 
    ? new HashMap<String, HttpSession>()
    : (Map<String, HttpSession>) application.getAttribute(USERS_MAP);
    // 先判断是否有相同的人已经登陆了,如果有就把已经登陆的Session注销
    if (map.size() > 0 && map.containsKey(uid)) {
    map.remove(uid).invalidate();
    }
    map.put(uid, session);
    application.setAttribute(USERS_MAP, map);
    }// /**
    //  * 是否已存在该用户的登录
    //  * 
    //  * @return
    //  */
    // @SuppressWarnings("unchecked")
    // private boolean isExist() {
    // // 表单中的用户名
    // String uid = request.getParameter(PARAM_UID);
    // // application中,用户名表列表
    // Set set = (Set) application.getAttribute(USERS_MAP) == null ? new HashSet()
    // : (Set) application.getAttribute(USERS_MAP);
    //
    // if (set.contains(uid)) {
    // request.setAttribute(MSG, MSG_USEING);
    // return true;
    // } else {
    // return false;
    // }
    // } /**
     * 初始化,赋值application
     */
    public void init(FilterConfig config) throws ServletException {
    this.application = config.getServletContext();
    } public void destroy() {
    }
    }同一时间只允许有一个浏览器使用该系统.
    当使用相同用户登录时,会把之前登录的挤下线
      

  28.   

    判断SESSION里是否有该用户就OK了。
      

  29.   

    我是楼猪,
    session失效,怎么实现自动跳转?
      

  30.   

    汗!我做过一次是用session判断 ,但是只能是在本机上面不允许相同账号的登录。。很汗
      

  31.   

    请问9楼的办法在JSP页面中怎么用呢