如何做到同⼀个账号同⼀时段只能登录⼀个
在许多web 项⽬中,需要禁⽌⽤户重复登录。⼀般来说有两种做法:
⼀是在⽤户表中维护⼀个字段isOnLine(是否在线),⽤户登录时,设定值为true ,⽤户退出时设定为false ,在重复登录时,检索到该字段为true 时,禁⽌⽤户登录。这种⽅法有明显的漏洞,及⽤户在⾮正常情况退出(关闭浏览器、关机等)是,该字段值⼀直为true ,会导致⽤户⽆法登录。
⽽另⼀种⽐较通⽤的做法是使⽤session 监听,重复登录后,强制之前登录的session 过期,从⽽踢出了该⽤户。具体做法是:使⽤维护服务器上缓存的sessionMap ,该map 是以&Id(),session>的键值对,在登录后,使⽤userid 替换Id(),从⽽使得sessionMap 中维护的是<userid, session>的键值对。后续该帐号重复登录时,检索到已有该帐号session 则强制它过期。
1、l 中配置session 监听
2、session 监听SessionListener 类
SessionContex 类(使⽤单例模式)[html]
01. <listener>  02.        <listener-class>compc.framework.listener.SessionListener </listener-class>          03. </listener>  [html]
01. package compc.framework.listener;  02.  03. import javax.servlet.http.HttpSessionEvent;  04. import javax.servlet.http.HttpSessionListener;  05.  06. import compc.framework.utils.SessionContext;  07.  08. public class SessionListener implements HttpSessionListener {  09.    public  static SessionContext sessionContext =SessionContext .getInstance();  10.    11.    public void sessionCreated(HttpSessionEvent httpSessionEvent) {  12.        sessionContext.Session());  13.    }  14.  15.    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {  16.        sessionContext.Session());  17.    }  18. }  [html]session如何设置和读取
01. package compc.framework.utils;  02.  03. import java.util.HashMap;  04.  05. import javax.servlet.http.HttpSession;  06.  07.  08. public class SessionContext {  09.    private static SessionContext instance;  10.    private HashMap <String ,HttpSession > sessionMap;  11.    12.    private SessionContext() {  13.        sessionMap  = new  HashMap <String ,HttpSession >();  14.    }  15.  16.    public static SessionContext getInstance() {  17.        if (instance  == null) {  18.            instance  = new  SessionContext();  19.        }  20.        return instance;  21.    }  22.  23.    public sync
hronized void AddSession(HttpSession session) {  24.        if (session != null) {  25.            sessionMap.Id(), session);  26.        }  27.    }  28.
3、⽤户登录成功后,更新session Map ,如重复登录,强制之前session 过期
4、spring MVC 校验session 是否过期,如果过期,给出提⽰,并跳转到登录界⾯。
配置
authInterceptor 29.    public synchronized void DelSession(HttpSession session) {  30.        if (session != null) {  31.            Id());  32.            Attribute("userid")!=null){  33.                Attribute("userid").toString());  34.                //session.invalidate();  35.            }  36.        }  37.    }  38.  39.    public synchronized HttpSession getSession(String session_id) {  40.        if (session_id  == null) return null;  41.        return (HttpSession) (session_id);  42.    }  43.  44.    public HashMap getSessionMap() {  45.        return s
essionMap;  46.    }  47.  48.    public void setMymap(HashMap sessionMap) {  49.        this.sessionMap  = sessionMap ;  50.    }  51.  52. }  [html]
01. public void sessionHandlerByCacheMap(HttpSession session){  02.        String userid =session .getAttribute("userid").toString();  03.        if(SessionMap().get(userid)!=null){  04.            HttpSession userSession =(HttpSession)SessionMap().get(userid);  05.            //注销在线⽤户  06.            userSession.invalidate();            07.            SessionMap().remove(userid);  08.            //清除在线⽤户后,更新map,替换map sessionid  09.            SessionMap().Id());  10.            SessionMap().put(userid,session);  11.        }  12.        else  13.        {  14.            // 根据当前sessionid 取session 对象。 更新map key =⽤户名 value =session 对象 删除map  15.                SessionMap().Id());  16.            SessionMap().put(userid,SessionMap().Id())17.            SessionMap().Id());  18.        }  19.    }
[html]
01.      <init-param>  02.            <description>Spring MVC 配置⽂件</description>  03.            <param-name>contextConfigLocation </param-name>  04.            <param-value>l </param-value>  05.        </init-param>
[html]
01. <mvc:interceptors>    02.        <bean  class ="compc.framework.interceptor.AuthInterceptor" />    03.    </mvc:interceptors>
[html]
01. package compc.framework.interceptor;  02.  03. import java.io.PrintWriter;
以上Sprring MVC 在同服务器以ajax ⽅式交互时,前台需做如下相应处理:04. import java.util.Map;  05.  06. import javax.annotation.Resource;  07. import javax.servlet.http.HttpServletRequest;  08. import javax.servlet.http.HttpServletResponse;  09.  10. import org.springframework.stereotype.Component;  11. import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;  12.  13. import compc.fram
eworkmon.SessionContainer;  14.  15. @Component("SpringMVCInterceptor")  16. public class AuthInterceptor extends HandlerInterceptorAdapter {      17.      18.    @Override  19.    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  20.        request.setCharacterEncoding("UTF-8");  21.        response.setCharacterEncoding("UTF-8");  22.        response.setContentType("text/html;charset =UTF -8");  23.    24.        //过滤登录、退出访问  25.        String[] noFilters  = new  String[] { "/auth/login", "/auth/logout" };  26.        String uri  = request .getRequestURI();  27.  28.        boolean beFilter  = true ;  29.        for (String s : noFilters) {  30.            if (uri.indexOf(s) != -1) {  31.                beFilter  = false ;  32.                break;  33.            }  34.        }  35.        SessionContainer sessionContainer  = (SessionContainer) Session().getAttribute("SessionContainer");  36.        if (beFilter) {  37.            if (null  == sessionContainer) {  38.                //ajax ⽅式交互  39.                if (Header("x-requested-with") != null  40.
&& Header("x-requested-with").equalsIgnoreCase("XMLHttpRequest"))// 如果是ajax 请求响应头会有,x-requested-with ;  41.                {                    42.                    response.setHeader("sessionstatus", "timeout");// 在响应头设置session 状态  43.                    return false;  44.                }  45.                // 未登录  46.                PrintWriter out  = response .getWriter();  4
7.                StringBuilder builder  = new  StringBuilder();  48.                builder.append("<script  type =\"text/javascript\" charset =\"UTF-8\">");  49.                builder.append("alert(\"页⾯过期,请重新登录\");");  50.                builder.append("p.location.href ='/auth/logout';");  51.                builder.append("</script>");  52.                out.String());  53.                out.close();  54.                return false;  55.            } else {                      56.                // 添加系统⽇志  57.                // -----------------------------------  58.                // -----------------------------------  59.            }  60.        }  61.        Map paramsMap  = request .getParameterMap();  62.        return super.preHandle(request, response, handler);  63.    }  64. }
[html]
01. //控制ajax 请求,session 超时处理页⾯跳转  02.  $.ajaxSetup({    03.        contentType:"application/x-www-form-urlencoded;charset =utf -8",    04.        complete:function(XMLHttpRequest,textStatus){    05.
var sessionstatus =XMLHttpRequest .getResponseHeader("sessionstatus"); // 通过XMLHttpRequest 取得响应头,sessionstatus ,  06.                if(sessionstatus =="timeout"){    07.                      // 如果超时就处理 ,指定要跳转的页⾯    08.                      alert("页⾯过期,请重新登录");  09.                      p.location.href ="/auth/logout";  10.                    }
以上⽅式完成了禁⽌⽤户重复登录的功能,并将踢出之前登录的帐号,这在不同的浏览器中使⽤没有问题。但是因为在同⼀个浏览器中,多个标签页(Tab 页)是共享session 的,在同⼀个浏览器中并不会创建⼀个新的session 。所以同⼀个浏览器还是可以重复登录的,⽬前还没有什么很好解决办法。本来想如果重复登录,则通过校验session 是否存在来禁⽌登录。但是之前登录的若关闭了标签页,则在这个浏览器上的其他标签页则再也⽆法登录了。所以这个做法也有问题。11.                  }      12.                }  13.          );

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。