由於對用戶數據的安全性考慮,在同一時刻不允許兩個相同的用戶存在(SSM架構下)。
場景,假設 Tom使用了用戶1,Joker也是使用了用戶1,兩人同時對用戶1 的相關數據進行了修改,就會造成數據的安全隱患。
思路:
1.定義一個key-value結構的用戶棧,將用戶名與sessionId綁定,存入用戶棧中
2.設置攔截器,攔截請求,判斷該用戶的sessionId是否與系統中的sessionId一致
這里的用戶棧可以使用ServletContext,其作用域為application,在用戶登錄成功的時候,將sessionId存入ServletContext,並在攔截過程中,以用戶名為Key值判斷sessionId的一致性。
實現:
在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"; }
}
攔截器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(operator.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>
說明:
后一個用戶登錄系統時,會替換用戶棧對應的sessionId,需要前一個用戶發起任意請求時,才會被強制跳轉到異地登錄提示頁面