I have an interceptor to handle the user session. If the user
attribute does not exist, then the interceptor will redirect to the signin page. I want to send a session timeout
message with the redirect url, but I don't want the message in the url. I google a lot for the RedirectAttributes
or FlashMap
, but I can't find any good solution.
public class UserSessionInterceptor extends HandlerInterceptorAdapter {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
User user = (User)request.getSession().getAttribute(CommonConstants.USER_SESSION_KEY);
if (user == null) {
String msg = String.format("session timeout");
logger.error(msg);
// response.sendRedirect("/signin?errorMessage=" + msg); //I don't want to do this..
return false;
}
return true;
}
}
signinController snippet:
@Controller
@SessionAttributes(CommonConstants.KAPTCHA_SESSION_KEY)
public class SigninController extends BaseController {
@RequestMapping(value = "/signin", method = RequestMethod.GET)
public String signinPage() {
return "forward:/index.jsp";
}
@RequestMapping(value = "/signin", method = RequestMethod.POST)
public String signin(UserForm userForm, @ModelAttribute(CommonConstants.KAPTCHA_SESSION_KEY) String captchaExpected, RedirectAttributes redirectAttributes, HttpServletRequest request) {
userForm.setCaptchaExpected(captchaExpected);
try {
loginValidator.validate(userForm);
} catch (ValidateFailedException e) {
logger.error(e.getMessage(), e);
redirectAttributes.addFlashAttribute(ERROR_MESSAGE_KEY, e.getMessage());
return "redirect:/signin";
}
User user = userService.getByUsername(userForm.getUsername());
if (user == null || !user.getPassword().equals(DigestUtils.md5Hex(userForm.getPassword()))) {
redirectAttributes.addFlashAttribute(ERROR_MESSAGE_KEY, "username or password is invalid");
return "redirect:/signin";
}
request.getSession().setAttribute(CommonConstants.USER_SESSION_KEY, user);
return "redirect:/dashboard";
}
}
index.jsp snippet:
<%@page contentType="text/html; charset=utf-8"%>
<%@ include file="/WEB-INF/jsp/include.jsp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>welcome</title>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="keywords" content="" />
<meta http-equiv="description" content="" />
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="${ctx}/css/bootstrap.min.css">
<link rel="stylesheet" href="${ctx}/css/main.css">
<script src="${ctx}/js/jquery-1.11.1.min.js"></script>
<script src="${ctx}/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="login-box text-center" >
<div class="login-single-panel-header">
<h5 style="color:red">${errorMessage}</h5>
</div>
</div>
</div>
</body>
</html>
Thank you very much!
We have to wire the spring interceptor to the requests, we can use mvc:interceptors element to wire all the interceptors. We can also provide URI pattern to match before including the spring interceptor for the request through mapping element. Our final spring bean configuration file (spring. xml) looks like below.
You can use RedirectAttributes to store flash attributes and they will be automatically propagated to the "output" FlashMap of the current request. A RedirectAttributes model is empty when the method is called and is never used unless the method returns a redirect view name or a RedirectView.
We can use a name such as a redirect: http://localhost:8080/spring-redirect-and-forward/redirectedUrl if we need to redirect to an absolute URL.
In order to use Flash attribute in your Spring MVC application make sure you using version 3.1 or above. Also add mvc:annotation-driven to spring-servlet. xml file. Once this is done, Flash attribute is automatically set “on” for usage.
I just encountered the same problem. I debuged the spring source code,looking for how spring mvc same the flashmap attributes,and came up with that it same flashmap attributes in sessions.
here is my last solution:
// create a flashmap
FlashMap flashMap = new FlashMap();
// store the message
flashMap.put("ERROR_MESSAGE", "this is the message");
// create a flashmapMapManger with `request`
FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request);
// save the flash map data in session with falshMapManager
flashMapManager.saveOutputFlashMap(flashMap, request, response);
org.springframework.web.servlet.view.RedirectView#renderMergedOutputModel
,you may check it youselfwish this will help you!
Here is another way of doing it in Spring 5.0
public class LoginInterceptor extends HandlerInterceptorAdapter{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String loginUrl = request.getContextPath() + "/login";
if(request.getSession().getAttribute("loggedInUser") == null) {
FlashMap outputFlashMap = RequestContextUtils.getOutputFlashMap(request);
outputFlashMap.put("loginError", "Please login to continue");
//New utility added in Spring 5
RequestContextUtils.saveOutputFlashMap(loginUrl, request, response);
response.sendRedirect(loginUrl);
return false;
}
return true;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With