- 浏览: 3425011 次
- 性别:
- 来自: 珠海
文章分类
- 全部博客 (1633)
- Java (250)
- Android&HTML5 (111)
- Struts (10)
- Spring (236)
- Hibernate&MyBatis (115)
- SSH (49)
- jQuery插件收集 (55)
- Javascript (145)
- PHP (77)
- REST&WebService (18)
- BIRT (27)
- .NET (7)
- Database (105)
- 设计模式 (16)
- 自动化和测试 (19)
- Maven&Ant (43)
- 工作流 (36)
- 开源应用 (156)
- 其他 (16)
- 前台&美工 (119)
- 工作积累 (0)
- OS&Docker (83)
- Python&爬虫 (28)
- 工具软件 (157)
- 问题收集 (61)
- OFbiz (6)
- noSQL (12)
最新评论
-
HEZR曾嶸:
你好博主,这个不是很理解,能解释一下嘛//左边+1,上边+1, ...
java 两字符串相似度计算算法 -
天使建站:
写得不错,可以看这里,和这里的这篇文章一起看,有 ...
jquery 遍历对象、数组、集合 -
xue88ming:
很有用,谢谢
@PathVariable映射出现错误: Name for argument type -
jnjeC:
厉害,困扰了我很久
MyBatis排序时使用order by 动态参数时需要注意,用$而不是# -
TopLongMan:
非常好,很实用啊。。
PostgreSQL递归查询实现树状结构查询
http://blog.csdn.net/jrn1012/article/details/25781319
在许多web项目中,需要禁止用户重复登录。一般来说有两种做法:
一是在用户表中维护一个字段isOnLine(是否在线),用户登录时,设定值为true,用户退出时设定为false,在重复登录时,检索到该字段为true时,禁止用户登录。这种方法有明显的漏洞,及用户在非正常情况退出(关闭浏览器、关机等)是,该字段值一直为true,会导致用户无法登录。
而另一种比较通用的做法是使用session监听,重复登录后,强制之前登录的session过期,从而踢出了该用户。具体做法是:使用监听器维护服务器上缓存的sessionMap,该map是以<session.getId(),session>的键值对,在登录后,使用userid替换session.getId(),从而使得sessionMap中维护的是<userid, session>的键值对。后续该帐号重复登录时,检索到已有该帐号session则强制它过期。
1、web.xml中配置session监听
2、session监听SessionListener类
SessionContex类(使用单例模式)
3、用户登录成功后,更新session Map,如重复登录,强制之前session过期
4、spring MVC拦截器校验session是否过期,如果过期,给出提示,并跳转到登录界面。
拦截器配置
拦截器authInterceptor
以上方式完成了禁止用户重复登录的功能,并将踢出之前登录的帐号,这在不同的浏览器中使用没有问题。但是因为在同一个浏览器中,多个标签页(Tab页)是共享session的,在同一个浏览器中并不会创建一个新的session。所以同一个浏览器还是可以重复登录的,目前还没有什么很好解决办法。本来想如果重复登录,则通过校验session是否存在来禁止登录。但是之前登录的若关闭了标签页,则在这个浏览器上的其他标签页则再也无法登录了。所以这个做法也有问题。
在许多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 sessionid SessionListener.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是否过期,如果过期,给出提示,并跳转到登录界面。
拦截器配置
<init-param> <description>Spring MVC配置文件</description> <param-name>contextConfigLocation</param-name> <param-value>classpath:controller.xml</param-value> </init-param> controller.xml配置 [html] view plaincopy在CODE上查看代码片派生到我的代码片 <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 { @Override public 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方式交互时,前台需做如下相应处理: [html] view plaincopy在CODE上查看代码片派生到我的代码片 //控制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是否存在来禁止登录。但是之前登录的若关闭了标签页,则在这个浏览器上的其他标签页则再也无法登录了。所以这个做法也有问题。
发表评论
-
Spring Boot 属性配置
2016-06-24 11:04 1183Spring Boot 属性配置和使用 http://blog ... -
Spring Boot 集成MyBatis
2016-06-24 10:55 2028Spring Boot 集成MyBatis http://bl ... -
Spring MVC防重复提交
2016-06-17 15:47 1646http://my.oschina.net/zyqjustin ... -
Spring容器加载完之后执行特定任务
2016-06-17 15:36 2288http://my.oschina.net/simpleton ... -
使用spring-session和shiro来代理session的配置
2016-06-16 11:21 12060使用spring-session和redis来代理sessio ... -
JSTL 的 if else : 有 c:if 没有 else 的处理
2016-06-14 09:52 1337http://blog.csdn.net/xiyuan1999 ... -
spring mvc 请求转发和重定向
2016-06-14 09:48 1400http://blog.csdn.net/jackpk/art ... -
mvc:view-controller
2016-05-18 10:26 1084http://blog.csdn.net/lzwglory/a ... -
spring配置事物的方式:注解和aop配置
2016-05-14 00:26 4104参考: Spring AOP中pointcut express ... -
分布式任务调度组件 Uncode-Schedule
2016-05-13 14:47 2287http://www.oschina.net/p/uncode ... -
Mybatis分库分表扩展插件
2016-05-12 15:47 1625http://fangjialong.iteye.com/bl ... -
spring+mybatis+atomikos 实现JTA事务
2016-05-11 22:00 5524sping配置多个数据源 不同用户操作不同数据库 http:/ ... -
Spring中使用注解 @Scheduled执行定时任务
2016-05-10 09:39 1567原文:http://dwf07223.blog.51cto.c ... -
Spring中配置Websocket
2016-05-05 16:55 1278spring+websocket整合(springMVC+sp ... -
redis 集群中Session解决方案之Spring Session
2016-05-04 08:54 1316集群中Session解决方案之Spring Session h ... -
使用Spring-data进行Redis操作
2016-05-04 08:54 4795使用Spring-data进行Redis操作 http://z ... -
Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC
2016-05-03 13:35 1062Spring4新特性——集成Bean Validation 1 ... -
SpringMVC介绍之Validation
2016-05-03 13:10 985SpringMVC介绍之Validation http://h ... -
spring 注解方式下使用commons-validator 验证表单
2016-05-03 11:08 3078原文: http://www.programgo.com/ar ... -
Spring MVC学习详解
2016-04-28 09:13 1004原文 http://blog.csdn.net/alsocod ...
相关推荐
在本篇文章中,我们详细探讨了如何通过Spring MVC拦截器实现session的控制,特别是在处理用户登录状态和防止重复登录的场景。 首先,session监听是实现session控制的一种常见方法,通过实现特定的监听器接口,可以...
以上就是使用`SessionListener`、持久化`Session`和`Springmvc拦截器`实现单点登录的基本原理和实现步骤。通过这样的设计,可以有效地提升用户体验,同时确保系统的安全性。在实际项目中,还需要根据具体需求进行...
如果不存在,表示用户没有登录或者session已经过期,此时拦截器会拦截请求,并通过客户端的JavaScript弹出提示框,通知用户重新登录,并通过`window.location.href`指向注销路径`/user/logout`,从而实现对未登录或...
Spring Session提供了拦截器、过滤器等多种集成方式,使得在Spring应用中集成非常方便。 其次,Hibernate 5是一个流行的Java ORM框架,用于简化数据库操作。它允许开发人员使用Java对象来操作数据库记录,而不是...
2. **Spring MVC拦截器**:实现HandlerInterceptor接口,利用preHandle、postHandle和afterCompletion方法进行拦截操作。 3. **JDBC**:使用JDBC API进行数据库连接、查询和操作,实现用户身份验证。 通过这个实验...
其强大的拦截器机制和丰富的插件库,使得它在处理复杂的Web应用时表现出色。Struts2与Spring3的整合,可以利用Spring的依赖注入(DI)和面向切面编程(AOP)特性,使Struts2的动作类更加灵活和解耦。 Spring3框架则...
我们创建一个`SessionListener`,在session创建时记录用户登录,在session销毁时记录用户退出。 11. **配置Web.xml** 在`WEB-INF/web.xml`中,我们需要配置Spring MVC的DispatcherServlet,以及过滤器和监听器的...
在"springmvc-chapter2"这个文件中,可能包含了项目的源代码,包括Spring MVC配置文件(如`servlet-context.xml`)、拦截器实现类、Session管理相关代码以及控制器类。通过阅读和理解这些代码,可以更深入地了解...
在用户登录时,我们通常会将用户的登录信息(如用户ID或用户名)存入session,以便在后续请求中判断用户是否已登录。当用户在其他设备或浏览器上再次登录时,我们需要检测并处理可能存在的异地登录冲突。 Spring...
Struts2.0是ActionServlet的升级版,它提供了强大的MVC框架,支持拦截器、OGNL表达式、动态方法调用等特性,使得视图和控制逻辑的分离更加彻底。在"Struts2.0+Hibernate+Spring(一)"这个主题中,我们首先会学习如何...
定义拦截器类,实现Interceptor接口或使用Spring提供的HandlerInterceptorAdapter抽象类。 2. 在Spring配置文件中注册拦截器。 3. 配置哪些路径需要被拦截器处理。 - **一个例子**: - 创建一个名为`...
**Struts2配置**:Struts2的配置主要集中在`struts.xml`中,定义Action、拦截器、结果类型等,确保框架能够根据配置处理请求。 #### CRUD功能开发流程 1. **实体类设计**:基于业务需求设计实体类,并使用...
WebWork 提供了强大的动作映射和拦截器机制,使得开发者可以轻松地管理用户请求,并实现复杂的业务逻辑。在整合中,WebWork 通常负责接收 HTTP 请求,解析参数,然后调用相应的服务层方法处理业务。 Spring 框架是 ...
Struts2提供了拦截器机制,可以方便地添加日志、权限检查等通用功能,同时支持多种结果类型,如JSP、FreeMarker、Velocity等。在Struts2中,配置文件(struts.xml)用于定义Action、结果类型、拦截器栈等,实现灵活...
4、拦截器可以利用依赖注入,因此在spring框架程序中,优先拦截器 5、拦截器是包裹在过滤器中使用的。 复习 converter 转换器 i18n struts2 spring MVC 拦截器 interceptor 过滤器 filter web.xml ...
1. **Spring MVC与WebWork集成**:通过Spring的Servlet监听器,可以配置WebWork的动作上下文,实现请求的分发。Spring MVC的DispatcherServlet可以转发请求到WebWork的Action,这样既保留了WebWork的强项,又利用了...
Struts2是一个强大的MVC框架,它提供了丰富的控制器组件和拦截器机制,可以处理HTTP请求并转发到相应的业务逻辑。Struts2的核心在于Action和Result,Action代表用户的一个操作,Result则是操作后的返回结果。此外,...
2. **拦截器处理:** 请求到达后,首先由拦截器栈处理。 3. **参数绑定:** 自动绑定请求参数到 Action 类中的属性。 4. **业务逻辑处理:** 执行 Action 类中的方法。 5. **结果返回:** 返回一个结果类型来控制...
Struts2的核心组件包括Action类、拦截器、结果类型等。 #### 二、Hibernate简介与应用场景 **Hibernate**是一种对象关系映射(ORM)工具,用于在Java应用程序中处理数据库交互。通过将Java对象映射到数据库表,...
在IT领域,掌握Java、SQL、Oracle、EJB、SSH、Struts、XML以及监听器、拦截器和过滤器等技术是至关重要的。这些技术涵盖了Web应用开发的多个层面,对于初学者而言,理解并熟练运用它们能为职业生涯打下坚实的基础。 ...