Now I have a login code like this,UserInfo is a form with username and password
#RequestMapping(value = "/login/loginCheck", method = RequestMethod.POST)
public Map<String, Object> loginCheck(UserInfo userInfo)
#RequestMapping(value = "/login/PageA", method = RequestMethod.POST)
public Map<String, Object> PageA(){
//maybe check the session
//if session expired ,then redirect to login page
}
After login, I should redirect page to Page A, and record the username in session, So in spring framework, Do I just configure it or get Session from request ?
Hope to be clear.
There are many ways, one is to simply inject HttpSession into your handler method
#RequestMapping(value = "/login/PageA", method = RequestMethod.POST)
public Map<String, Object> PageA(HttpSession httpSession){
//maybe check the session
//if session expired ,then redirect to login page
}
The getAttribute method of HttpSession will throw IllegalStateException if session is no longer valid, but I have a feeling Spring MVC will create a new session for you when that happen, so also check for non-existence (null value)
Also have a look at the usage of #SessionAttributes and #ModelAttribute annotation on Spring doc, and Spring Security framework
Related
I had an old application with Java and Struts.
I do some refactoring and recode this application with SpringBoot.
But I have a problem handling the redirection between application and some external url, keeping my session attribute values.
To simplify, I have two endpoints, one in post, one in get.
First, the POST endpoint is called :
#RequestMapping(value = "/Action.do", method = RequestMethod.POST)
public String saveConfigurationPost(HttpServletRequest request){
logger.info("Set session param");
request.getSession().setAttribute("someAttribute", "value");
return "redirect:http://external-url.fr#redirectUri=internal-server/Action.do"
}
The external website do some treatment, and redirect me back to my application with a get request on the specified uri Action.do
#RequestMapping(value = "/Action.do", method = RequestMethod.GET)
public String saveConfigurationGet(HttpServletRequest request){
String myParamValue = (String) request.getSession().getAttribute("someAttribute");
logger.info("Get session param : "+myParamValue); // Return null
....
return "success"
}
But after redirect me to the GET endpoint, I always have a null value for my session attribute.
Why ?
With my old application, I used new ActionForward(forwardUrl, true) to redirect.
How could I get the same thing, simple as possible ?
In Spring MVC, I can wire session with my method. That's OK.
#RequestMapping(value = "/{cid}/read")
public #ResponseBody
boolean markAsRead(#PathVariable("cid") Comment comment, HttpSession session) {
User user = ((User) session.getAttribute("user"));
... }
Can I wire above user definition to the method definition? I mean instead of wiring session
#RequestMapping(value = "/{cid}/read")
public #ResponseBody
boolean markAsRead(#PathVariable("cid") Comment comment, User user) {
//No need to inject HttpSession and
//no need to call user = ((User) session.getAttribute("user"));
... }
You should be able to retrieve it using the #ModelAttribute tag, and annotating the user as a session attribute, this way:
#SessionAttributes("user")
public class MyController {
#RequestMapping(value = "/{cid}/read")
public #ResponseBody
boolean markAsRead(#PathVariable("cid") Comment comment, #ModelAttribute("user") User user) {
//No need to inject HttpSession and
//no need to call user = ((User) session.getAttribute("user"));
... }
}
I am using #SessionAttributes in spring, but I don't know how to end the session, I tried the below code but I am getting error, Please give me some example.
Thanks.
#RequestMapping(value = "/LogoutAction")
public String logout(HttpServletRequest request) {
Resource res = new ClassPathResource("spring-context.xml");
BeanFactory factory = new XmlBeanFactory(res);
HttpSession session = request.getSession();
session.invalidate();
return "Login";
}
I think the common problem when using #SessionAttributes is after you invalidate your current session, Spring MVC attach the model attributes back into the new session -- hence causing the impression it never invalidates
You can check the value of JSESSIONID before & after you invalidate it. You will get a brand new JSESSIONID, yet previous model attributes are attached straight into the new session
I found myself having to do this to wipe a model attribute of name "counter" from session after invalidating it
#RequestMapping(value="/invalidate", method=RequestMethod.POST)
public String invalidate(HttpSession session, Model model) {
session.invalidate();
if(model.containsAttribute("counter")) model.asMap().remove("counter");
return "redirect:/counter";
}
If you have plenty attributes, ofcourse you can try wiping everything off using
model.asMap().clear();
But in my opinion better approach is to invalidate using a different controller that doesn't have #SessionAttribute on it. Hence whatever model attributes other controllers have won't be attached straight into the new session. Eg:
#Controller
#RequestMapping("/logout")
public class LogoutController {
#RequestMapping(method=RequestMethod.POST)
public String logout(HttpSession session) {
session.invalidate();
return "redirect:/login";
}
}
This also should work (similar to what was purposed by gerrytan... and some years late)... suppose that your #SessionAttributes saves the "stuff" object that you create under a #ModelAtributte method:
#ModelAttribute("patient")
public Patient newPatient() {
return new Patient();
}
/*
other methods to do stuffs...
*/
#RequestMapping(value = "/logout")
public String logout(HttpServletRequest request, Model m) {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
m.addAttribute("patient", newStuff());
return "redirect:/login";
}
So basically you capture the model send and you set a new object (of the type stored in the #SessionAtributte) and voilà... the SessionAttribute is still there but empty...
might be not the cleanest solution (i'm noob) but works in my local project)
My applications redirects after POST operation some information to the GET controller but lose the information when using with Apache and reverse proxy. When I do this operation without the reverse proxy in the middle everything works fine. Some ideas?
#PreAuthorize("hasRole('ROLE_ADMIN')")
#RequestMapping(value = "aCategory", method = RequestMethod.POST)
public String category(#RequestParam("aCategoryName") String name, Model model, RedirectAttributes attr,
HttpServletRequest request) {
String redirect = "redirect:" + "http://localhost:8080/aCategory";
aService.saveACategory(name);
attr.addFlashAttribute("aCategoryName", name);
return redirect;
}
#RequestMapping(value = "aCategory", method = RequestMethod.GET, produces = "text/html")
public String appCategory(Model model, Principal principal) {
String name = principal.getName(); // get logged in username
model.addAttribute("username", name);
return "aCategory";
}
It depends on your cluster configuration and session replication configuration. Because FlashAttributes are first stored in a session temporarily before adding it to the model map to display it on the redirected view. So if your cluster is not well configured for proper session replication then your FlashAttribute might be lost when request is served by another cluster than where the FlashAttribute is actually stored in session.
For further details you can refer my question.
Hope this helps you. Cheers.
I am using session.setAttribute to store user object after login. In next controller, I have #SessionAttribute for the same user and #ModelAttribute for same object to be used in the method mapped to a RequestMapping. After login if I click any link in the user home page it give
HttpSessionRequiredException: Session attribute '' required - not found in session
I am not sure what I am doing wrong. I went through many article and question in this site as well but could find any solution. The user object which I am storing in session stores user's account details which are required in all the controller to get different information from DB. I using SessionAttribute is wrong should I use HttpSession instead in all the controller and get the object from session manually or there is a proper way to handle in spring 3.0. Please note that this user object is not backing any form just login, but contains many other details.
As help would be good.
Have a look at my (non-perfect) use of session data:
#Controller
#SessionAttributes("sharedData")
public class RegistrationFormController {
#Autowired
private SharedData sharedData; // bean with scope="session"
#RequestMapping(value = {"/registrationForm"}, method = RequestMethod.GET)
public ModelAndView newForm() {
final ModelAndView modelAndView = new ModelAndView("registrationForm");
modelAndView.addObject("registrationForm", new RegistrationForm());
// I want to render some data from this object in JSP:
modelAndView.addObject("sharedData", sharedData);
return modelAndView;
}
#RequestMapping(value = {"/registrationForm"}, method = RequestMethod.POST)
public String onRegistrationFormSubmitted(HttpServletRequest request,
#ModelAttribute("registrationForm") RegistrationForm registrationForm, BindingResult result) {
if (result.hasErrors()) {
return "registrationForm";
}
// Perform business logic, e.g. persist registration data
return "formSubmitted";
}
}