背景說明
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = ((HttpServletRequest) request).getSession(); HttpServletResponse rep = (HttpServletResponse) response; HttpServletRequest req = (HttpServletRequest) request; String url = req.getRequestURI(); if (url.contains("user/login") || url.endsWith(".css") || url.endsWith(".js") || url.endsWith(".png") || url.endsWith(".jpg")) { chain.doFilter(request, response); } else if ((session == null || session.getAttribute("user") == null)) { rep.sendRedirect(req.getContextPath() + "/user/login); } else { chain.doFilter(request, response); } }
@RequestMapping(value = "/login", method = RequestMethod.GET) public ModelAndView login() { final ModelAndView m = new ModelAndView("login"); return m; } @RequestMapping(value = "/login", method = RequestMethod.POST) public ModelAndView login(HttpSession session, String userName, String password) { ReturnStatus rs = service.login(userName, MD5Tool.getMD5(password.getBytes())); if (rs.getCode() == 1) { session.setAttribute("user", service.get(userName)); return new ModelAndView("redirect:/task/week"); } else { final ModelAndView m = new ModelAndView("login"); m.addObject("message", "用戶名或者密碼不正確,請重新輸入"); return m; } }
解決方案
req.getRequestURI()
,獲取到的是/personal/task/update,不帶query string,不符合req.getRequestURL()
,獲取到的是http://localhost:8084/personal/task/update,也不帶query string,不符合- 於是我百度了一下,找到一下方法可以獲得完整的請求url(http://localhost:8084/personal/task/update?id=DTASK1167778733413045&mode=week),但是遺憾的是POST過來的數據還是無法
-
public static String getUrl(HttpServletRequest req) { String reqUrl = req.getRequestURL().toString(); String queryString = req.getQueryString(); if (queryString != null) { reqUrl += "?" + queryString; } return reqUrl; }
-
- 我試圖從request中把POST過來的數據設置到response的Header中,但是在login頁面經過SpringMVC後再次分發我又不會(感覺會很麻煩)
-
private void setHeader(HttpServletRequest req, HttpServletResponse rep) { for (Map.Entry<String, String[]> entry : req.getParameterMap().entrySet()) { try { String name = entry.getKey(); String value = new String(req.getParameter(name).getBytes("ISO8859-1"), "UTF8"); rep.setHeader(name, value); } catch (UnsupportedEncodingException ex) { Logger.getLogger(SessionFilter.class.getName()).log(Level.SEVERE, null, ex); } } }
-
- 於是決定,在POST的情況下就不再做POST操作,而是轉向到POST之前的界面(這樣有丟失數據的危險,暫時先這樣吧)
-
from Url = req.getHeader("Referer")
-
最終,思路確定如下:Session過濾時,如果是POST過來的,就取前一個頁面的url(第5點中的方法),如果是其他請求方式過來的(主要是GET),就使用當前要轉向的url(第3點中的方法)。將url通過GET方式傳入到login頁面後,POST login時也帶到後臺,待確認登陸成功後轉向到該url。
最終代碼
SessionFilter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = ((HttpServletRequest) request).getSession(); HttpServletResponse rep = (HttpServletResponse) response; HttpServletRequest req = (HttpServletRequest) request; String url = req.getRequestURI(); if (url.contains("user/login") || url.endsWith(".css") || url.endsWith(".js") || url.endsWith(".png") || url.endsWith(".jpg")) { chain.doFilter(request, response); } else if ((session == null || session.getAttribute("user") == null)) { String fromUrl; if ("POST".equalsIgnoreCase(req.getMethod())) { fromUrl = req.getHeader("Referer"); } else { fromUrl = getUrl(req); } rep.sendRedirect(req.getContextPath() + "/user/login?fromUrl=" + URLEncoder.encode(fromUrl, "UTF8")); } else { chain.doFilter(request, response); } } public static String getUrl(HttpServletRequest req) { String reqUrl = req.getRequestURL().toString(); String queryString = req.getQueryString(); if (queryString != null) { reqUrl += "?" + queryString; } return reqUrl; }
LoginController
@RequestMapping(value = "/login", method = RequestMethod.GET) public ModelAndView login(HttpServletRequest request, @RequestParam(defaultValue = "") String fromUrl) { final ModelAndView m = new ModelAndView("login"); m.addObject("fromUrl", fromUrl); return m; } @RequestMapping(value = "/login", method = RequestMethod.POST) public ModelAndView login(HttpSession session, String userName, String password, @RequestParam(defaultValue = "") String fromUrl) { ReturnStatus rs = service.login(userName, MD5Tool.getMD5(password.getBytes())); if (rs.getCode() == 1) { session.setAttribute("user", service.get(userName)); if (fromUrl.equals("")) { return new ModelAndView("redirect:/task/week"); } else { return new ModelAndView("redirect:" + fromUrl); } } else { final ModelAndView m = new ModelAndView("login"); m.addObject("message", "用戶名或者密碼不正確,請重新輸入"); m.addObject("fromUrl", fromUrl); return m; } }
http://www.alanzeng.cn/2016/01/login-redirect/