使用session监听+spring MVC拦截器禁止用户重复登录
来源:互联网 发布:淘宝疯马皮哪家好 编辑:程序博客网 时间:2024/05/21 14:04
在许多web项目中,需要禁止用户重复登录。一般来说有两种做法:
一是在用户表中维护一个字段isOnLine(是否在线),用户登录时,设定值为true,用户退出时设定为false,在重复登录时,检索到该字段为true时,禁止用户登录。这种方法有明显的漏洞,及用户在非正常情况退出(关闭浏览器、关机等)是,该字段值一直为true,会导致用户无法登录。
而另一种比较通用的做法是使用session监听,重复登录后,强制之前登录的session过期,从而踢出了该用户。具体做法是:使用监听器维护服务器上缓存的sessionMap,该map是以<session.getId(),session>的键值对,在登录后,使用userid替换session.getId(),从而使得sessionMap中维护的是<userid, session>的键值对。后续该帐号重复登录时,检索到已有该帐号session则强制它过期。
1、web.xml中配置session监听
<listener> <listener-class>com.cnpc.framework.listener.SessionListener</listener-class></listener>
2、session监听SessionListener类
package com.cnpc.framework.listener;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener;import com.cnpc.framework.utils.SessionContext;public class SessionListener implements HttpSessionListener { public static SessionContext sessionContext=SessionContext.getInstance(); public void sessionCreated(HttpSessionEvent httpSessionEvent) { sessionContext.AddSession(httpSessionEvent.getSession()); } public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { sessionContext.DelSession(httpSessionEvent.getSession()); }}SessionContex类(使用单例模式)
package com.cnpc.framework.utils;import java.util.HashMap;import javax.servlet.http.HttpSession;public class SessionContext { private static SessionContext instance; private HashMap<String,HttpSession> sessionMap; private SessionContext() { sessionMap = new HashMap<String,HttpSession>(); } public static SessionContext getInstance() { if (instance == null) { instance = new SessionContext(); } return instance; } public synchronized void AddSession(HttpSession session) { if (session != null) { sessionMap.put(session.getId(), session); } } public synchronized void DelSession(HttpSession session) { if (session != null) { sessionMap.remove(session.getId()); if(session.getAttribute("userid")!=null){ sessionMap.remove(session.getAttribute("userid").toString()); //session.invalidate(); } } } public synchronized HttpSession getSession(String session_id) { if (session_id == null) return null; return (HttpSession) sessionMap.get(session_id); }public HashMap getSessionMap() {return sessionMap;}public void setMymap(HashMap sessionMap) {this.sessionMap = sessionMap;}}
3、用户登录成功后,更新session Map,如重复登录,强制之前session过期
public void sessionHandlerByCacheMap(HttpSession session){String userid=session.getAttribute("userid").toString();if(SessionListener.sessionContext.getSessionMap().get(userid)!=null){HttpSession userSession=(HttpSession)SessionListener.sessionContext.getSessionMap().get(userid);//注销在线用户userSession.invalidate();SessionListener.sessionContext.getSessionMap().remove(userid);//清除在线用户后,更新map,替换map sessionidSessionListener.sessionContext.getSessionMap().remove(session.getId());SessionListener.sessionContext.getSessionMap().put(userid,session);}else{// 根据当前sessionid 取session对象。 更新map key=用户名 value=session对象 删除map SessionListener.sessionContext.getSessionMap().get(session.getId());SessionListener.sessionContext.getSessionMap().put(userid,SessionListener.sessionContext.getSessionMap().get(session.getId()));SessionListener.sessionContext.getSessionMap().remove(session.getId());}}
4、spring MVC拦截器校验session是否过期,如果过期,给出提示,并跳转到登录界面。
拦截器配置
web.xml配置
<init-param> <description>Spring MVC配置文件</description> <param-name>contextConfigLocation</param-name> <param-value>classpath:controller.xml</param-value> </init-param>controller.xml配置
<mvc:interceptors> <bean class="com.cnpc.framework.interceptor.AuthInterceptor" /> </mvc:interceptors>
拦截器authInterceptor
package com.cnpc.framework.interceptor;import java.io.PrintWriter;import java.util.Map;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.stereotype.Component;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import com.cnpc.framework.common.SessionContainer;@Component("SpringMVCInterceptor")public class AuthInterceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); //过滤登录、退出访问String[] noFilters = new String[] { "/auth/login", "/auth/logout" };String uri = request.getRequestURI();boolean beFilter = true;for (String s : noFilters) {if (uri.indexOf(s) != -1) {beFilter = false;break;}}SessionContainer sessionContainer = (SessionContainer) request.getSession().getAttribute("SessionContainer");if (beFilter) {if (null == sessionContainer) {//ajax方式交互if (request.getHeader("x-requested-with") != null&& request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest"))// 如果是ajax请求响应头会有,x-requested-with;{response.setHeader("sessionstatus", "timeout");// 在响应头设置session状态return false;}// 未登录PrintWriter out = response.getWriter();StringBuilder builder = new StringBuilder();builder.append("<script type=\"text/javascript\" charset=\"UTF-8\">");builder.append("alert(\"页面过期,请重新登录\");");builder.append("window.top.location.href='/auth/logout';");builder.append("</script>");out.print(builder.toString());out.close();return false;} else { // 添加系统日志// -----------------------------------// -----------------------------------}}Map paramsMap = request.getParameterMap();return super.preHandle(request, response, handler);}}
以上Sprring MVC拦截器在同服务器以ajax方式交互时,前台需做如下相应处理:
//控制ajax请求,session超时处理页面跳转 $.ajaxSetup({ contentType:"application/x-www-form-urlencoded;charset=utf-8", complete:function(XMLHttpRequest,textStatus){ var sessionstatus=XMLHttpRequest.getResponseHeader("sessionstatus"); // 通过XMLHttpRequest取得响应头,sessionstatus, if(sessionstatus=="timeout"){ // 如果超时就处理 ,指定要跳转的页面 alert("页面过期,请重新登录"); window.top.location.href="/auth/logout"; } } } );
以上方式完成了禁止用户重复登录的功能,并将踢出之前登录的帐号,这在不同的浏览器中使用没有问题。但是因为在同一个浏览器中,多个标签页(Tab页)是共享session的,在同一个浏览器中并不会创建一个新的session。所以同一个浏览器还是可以重复登录的,目前还没有什么很好解决办法。本来想如果重复登录,则通过校验session是否存在来禁止登录。但是之前登录的若关闭了标签页,则在这个浏览器上的其他标签页则再也无法登录了。所以这个做法也有问题。
0 0
- 使用session监听+spring MVC拦截器禁止用户重复登录
- 使用session监听+spring MVC拦截器禁止用户重复登录
- 使用session监听禁止用户重复登录
- 负载均衡下,数据库+Spring MVC拦截器禁止用户重复登录
- session监听防止用户登录重复
- session监听防止用户登录重复
- Spring mvc Session拦截器
- Spring mvc拦截器+angular js拦截器 做用户登录拦截控制
- spring mvc登录拦截器
- spring mvc登录拦截器
- spring 用户登录拦截器
- Spring MVC,拦截器实现session控制
- Spring MVC,拦截器实现session控制
- Spring MVC,拦截器实现session控制
- Spring MVC,拦截器实现session控制
- Spring Mvc session拦截器实现
- Spring MVC,拦截器实现session控制
- Spring MVC,拦截器实现session控制
- linux内核数据包转发流程(二):中断
- 使用BackgroundWorker在UI上操作主线程控件
- Navicat登录时出现的错误
- 发撒富商大贾是的鬼地方和
- Leetcode 线性表 Remove Duplicates from Sorted List II
- 使用session监听+spring MVC拦截器禁止用户重复登录
- UIScrollView 基础属性方法
- SVM学习——软间隔优化
- 媒体与电商的数据变现价值还是有些区别的,媒体除了广告增值之外还有什么?
- 关于PHP5.3作废函数的处理方法
- 谷歌浏览器的一个新特点—关于获取iframe的parent对象
- 安装 qwt6
- 如何将Emmet安装到到 Sublime text 3?
- 在互联网公司大举进军移动支付和网络理财之际 平安推出壹钱包对战互联网“群狼”