1.场景
假设 Tom使用了用户1,Joker也是使用了用户1,两人同时对用户1 的相关数据进行了修改,就会造成数据的安全隐患,得保证多台设备登录账号只有一个账号能登录上。
2.思路
- 2.1 利用ServletContext对象是全局存储对象(其作用域为application),key不可以重复,value可以重复的特性,将用户名和sessionid绑定存储起来。
- 2.2 首次登录在拦截器里面放行,登录成功将用户名和sessionid存储起来,当第二次登录时,用户名相同,sessionid不同的话则去登录,后面执行登录方法,把前一个账号和sessionid删除,然后把后一个的用户名和sessionid重新存起来,如果第二次登录时用户名相同,sessionid也相同,就直接放行,相当于单点登录。同一个会话sessionid是相同的,不同的会话sessionid肯定不同。
- 2.3 删除了sessionid的账号,只有点击一个操作后就会下线。
3.代码实现
拦截器userInterceptor代码示例:
public class userInterceptor implements HandlerInterceptor {
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
User user=(User)httpServletRequest.getSession().getAttribute("user");
String indexurl=httpServletRequest.getRequestURL().toString().replace(httpServletRequest.getRequestURI(),"");
ServletContext application = httpServletRequest.getSession().getServletContext();
if(user!=null){ //session中存在用户信息
String sessionId=application.getAttribute(user.getUserName()).toString();
if(sessionId.equals(httpServletRequest.getSession().getId())){
//请求的sessionId和此账号的sessionId一致,允许请求return true;
}else{
//如果请求的sessionId和此账号的sessionId不一致,跳转至异地登录提示页面
httpServletResponse.sendRedirect(indexurl+"/relogin");
return false;
}
}
//第一次登陆系统,session中没有记录,转发通过
httpServletRequest.getRequestDispatcher(indexurl).forward(httpServletRequest, httpServletResponse);
return true;
}
}
配置文件中设置拦截路径:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/statis/**"/> //exclude-mapping 不拦截的路径
<mvc:exclude-mapping path="/dologin"/>
<bean class="yi.survey.interceptor.UserInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
在controller的登录方法dologin方法示例:
@RequestMapping(value="/dologin",method = RequestMethod.POST)
public String dologin(@RequestParam User user,
HttpSession session, Model model){
//获取ServletContext对象
ServletContext application = session.getServletContext();
//查找数据库中的用户信息
User loginUser=userService.login(user);if(loginUser!=null){ //账号密码正确
String sessionId = session.getId();
if(application.getAttribute(userName) == null){
application.setAttribute(userName,sessionId);
}else if (application.getAttribute(userName)!= null && !StringUtils.equals(sessionId,application.getAttribute(userName).toString())){
application.removeAttribute(userName);
application.setAttribute(userName,sessionId);
}
//将用户信息存入session中
session.setAttribute("user", user);
// 页面跳转main.jsp
return "main";
}else{ //账号密码错误
model.addAttribute("error", "账号密码不正确");return "login";
}
}