Java Filter无限循环
我想实现一个filter来进行身份validation,但不知怎的,它被卡在无限循环中…任何想法都赞赏。
HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; doBeforeProcessing(request, response); Throwable problem = null; HttpSession session = httpRequest.getSession(true); if(session.getAttribute("userName")!=null&&session.getAttribute("userName")!=("")) { try { chain.doFilter(request, response); } catch (Throwable t) { // If an exception is thrown somewhere down the filter chain, // we still want to execute our after processing, and then // rethrow the problem after that. problem = t; t.printStackTrace(); } }else{ httpResponse.sendRedirect("login.jsp"); return; }
这个代码在调试模式下只运行无限次,基本上我想在用户没有登录时将用户重定向到login.jsp。任何答案都可以。
这里,
httpResponse.sendRedirect("login.jsp");
您正在为目标页面发送新的 HTTP请求,而不是使用当前请求。 如果这个新的HTTP请求被映射到过于通用的URL模式(例如/*
上,它当然会再次访问filter。 并且将执行相同的检查并且将再次重定向。 等等。 这是一个无休止的故事。
当前请求的页面是登录页面时,您还需要添加额外的检查来执行FilterChain#doFilter()
。
String loginURL = httpRequest.getContextPath() + "/login.jsp"; if (httpRequest.getRequestURI().equals(loginURL)) || session.getAttribute("userName") != null) { chain.doFilter(request, response); } else { httpResponse.sendRedirect(loginURL); }
请注意,我还删除了对空字符串的无意义检查作为用户名(但是你要确保你的代码无处设置一个空字符串作为用户名。只需使用null
来表示一个未登录的用户。另请注意我修复了重定向URL也是如此,因为当前请求的URL位于子文件夹中时它会失败。
另一种方法是将所有受限制的页面放在一个公共子文件夹中,例如/app
, /secured
, /restricted
等,然后将filter映射到/app/*
, /secured/*
, /restricted/*
的URL模式/restricted/*
等等。 如果将登录页面保留在此文件夹之外,则在请求登录页面时不会调用filter。
问题是您的filter在login.jsp
上运行,并且当用户未登录时将反复重定向到自身。 由于filterurl-pattern
上没有排除语法,因此如果您已经在login.jsp
页面上,则需要检测filter中的URL并省略重定向:
// your auth code } else { String redirect = httpRequest.getContextPath() + "/login.jsp"; String uri = httpRequest.getRequestURI().toString(); if (uri.endsWith(redirect)){ // URI ends with login.jsp, just process the chain chain.doFilter(); } else { // not on the login page and not logged in, redirect httpResponse.sendRedirect(redirect); return; } }