Spring Security - logout with my own message - spring

I'm developing Spring boot application. Thymeleaf on front is also used. Now I'm working on changing username(email). After confirmation from email I'm returning "redirect:/logout" in controller. I want to add a message that email is changed and user have to login again with new username(mail).
This is my configuration of Spring Security:
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login")
And controller fragment:
#RequestMapping(value = "/confirmmail/{hash}", method = RequestMethod.GET)
public String confirmMail(#PathVariable String hash,
RedirectAttributes redirectAttributes,
Model model) {
Optional<User> userOptional = userService.getUserByConfirmChangeEmailHash(hash);
if(userOptional.isPresent()){
User user = userOptional.get();
user.setEmail(user.getTemporaryEmail());
user.setTemporaryEmail(null);
userService.save(user);
redirectAttributes.addFlashAttribute("logoutMessage",messageService.getMessage("user.profile.email.changed.success"));
// redirectAttributes.addAttribute("message",messageService.getMessage("user.profile.email.changed.success"));
// model.addAttribute("logoutMessage",messageService.getMessage("user.profile.email.changed.success"));
return "redirect:/logout";
}else{
model.addAttribute("message",messageService.getMessage("user.profile.email.changed.failed"));
}
return "/user/index";
}
As you can see, I've tried to use RedirectAttributes, flash atributes, and simply to model.
Unfortunately, after redirecting to login page my data from model are not present.
How can I solve this problem?

Related

How to hook into Spring Security authentication process?

Currently I have this trivial configuration:
// Kotlin code
override fun configure(http: HttpSecurity) {
http
.formLogin()
.loginPage("/entry")
.loginProcessingUrl("/auth")
.usernameParameter("usr")
.passwordParameter("pwd")
.defaultSuccessUrl("/", true)
.failureHandler { request, response, exception ->
// Can't figure out what to enter here (see below).
}
}
If authentication fails, I have two requirements:
Flash error message into the session (avoiding 'error' param in query string). It seems I can't inject RedirectAttributes into this lambda; is there a workaround?
I want to send back the login (but not the password) that user entered before submitting login form, in order to repopulate the field. How do I do that?
I was able to figure it out.
#Configuration
#EnableWebSecurity
class SecurityConfig: WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http
.formLogin()
.loginPage("/entry")
.loginProcessingUrl("/auth")
.usernameParameter("usr")
.passwordParameter("pwd")
.defaultSuccessUrl("/", true)
.failureHandler { request, response, _ ->
request.session.setAttribute("loginError", "Login Error!")
request.session.setAttribute("failedUsername", request.getParameter("usr"))
response.sendRedirect("/entry")
}
}
}
Then, you have to set up login controller to customize serving of login form:
#Controller
#RequestMapping("/entry")
internal class LoginController {
#GetMapping
fun getLoginForm(session: HttpSession, model: Model): String {
if (session.getAttribute("loginError") != null) {
model.addAttribute("loginError", "Login Error!")
session.removeAttribute("loginError")
model.addAttribute("failedUsername", session.getAttribute("failedUsername"))
session.removeAttribute("failedUsername")
}
return "login"
}
}
Then, you can use loginError and failedUsername model attributes in your templates:
<div th:if="${loginError}">Incorrect login/password</div>
<!-- ... -->
<input type="text" name="usr" th:value="${failedUsername}">
Basically we are emulating "flashing" messages into session. We carry these messages in the session and remove them as soon as they are read and passed on into the model. It’s possible that redirect will go wrong and messages will remain in the session, but they are harmless on their own, plus they will be removed the next time user visits /entry page.
As a result, now there is no ?error in page URL, and the user is not required to retype username.

Spring : How to use session in Spring MVC

I have a login form and I want to display Name of user who logined .I want to use session in Spring MVC, but it's not work
This is UsersController
#PostMapping("/room/saveRegister")
public String saveRegister(#Valid Users users, BindingResult result, RedirectAttributes redirect) {
if (result.hasErrors()) {
return "register";
}
usersService.save(users);
redirect.addFlashAttribute("success", "Saved user successfully!");
return "redirect:/room";
}
#GetMapping("/room/login")
public String login(Model model) {
model.addAttribute("users", new Users());
return "login";
}
#PostMapping("/room/loginRoom")
public String login(#ModelAttribute("users") Users user, ModelMap modelMap, RedirectAttributes redirect,HttpSession session) {
if(usersService.findByEmailAndPass(user.getEmail(),user.getPass()) != null) {
session.setAttribute("name",user.getName());
return "redirect:/room";
}else {
modelMap.put("error", "Email or Password is not correct. Pleased Try Again");
return "login" ;
}
}
And in file .html,I add
<li ><span th:text ="${session.name}"></span></li>
But when I login successful . Name of User is not display . Session is not work. I don't know why
You need to use ${sessionScope.name} instead of ${session.name}
More details can be found at Examples of EL Expressions
Refer this
Using Http Session With Spring Based Web Applications

spring 4.1 javaConfg setting to get requestCache working

similar to this:
Spring 3.1: Redirect after login not working
when an authenticated user becomes inauthenticated while deep-linking into a single page web app.
Spring security redirects to logon but:
SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request, response);
is null
thus i cannot devine the url or params to send re-authenticated user to requested page
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers() //redacted .
.antMatchers("/**").permitAll()
.and()
.formLogin()
.loginPage("/x/y/logon")
.usernameParameter("userLogon") //redacted
.loginProcessingUrl("/x/y/logon") //redacted
.defaultSuccessUrl("/x/", true)
.failureUrl("/x/y/logon?error=true")
.and()
.logout()
.logoutUrl("/x/y/logout")
.logoutSuccessUrl("/x/")
.permitAll();
}
}
-- controller --
#RequestMapping(method=RequestMethod.GET, value="/y/logon")
public ModelAndView logonHandler(HttpServletRequest request, HttpServletResponse response) {
List<Client> clients = //manager call for list of clients to show at logon
SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request, response);
if (savedRequest != null) {
String reqUrl = savedRequest.getRedirectUrl();
String[] urlParams = reqUrl.split("&");
String prefix = "";
String urlParam = "";
String cid = "";
try {
urlParam = urlParams[1];
} catch(IndexOutOfBoundsException ioob) { }
if (reqUrl.contains("cid=")) { cid = reqUrl.substring(reqUrl.indexOf("cid=")+4, reqUrl.indexOf("&")); }
if (reqUrl.contains("?")) { reqUrl = reqUrl.substring(0, reqUrl.indexOf("?")); }
prefix = reqUrl.substring(reqUrl.indexOf("/x/")+6, reqUrl.indexOf("/x/")+8);
reqUrl = reqUrl.substring(reqUrl.indexOf(prefix)+2);
if (reqUrl.contains("/")) {
reqUrl = reqUrl.substring(0, reqUrl.indexOf("/"));
}
request.setAttribute("requestUrl", prefix+reqUrl);
request.setAttribute("urlParam", urlParam);
request.setAttribute("cid", cid);
}
request.setAttribute("IPAddress", request.getRemoteAddr());
return new ModelAndView("x/logon", "clients", clients);
}
problem is, SavedRequest is null
is this an issue with:
alwaysUseDefaultTargetUrl property?
if yes, how in javaConfig does one set this property?
----- on edit to address comments ------
i'll explain my understanding of ea. .formLogon() settings:
logonPage() will be read by spring and control redirect to logon page when you are not authorized (cookie expire/db record del, etc). There are many ways that a session can not be authorized and spring needs to know what page to send unauth requests to. My manual logon handler only handles requests to the logon url.
usernameParameter() is to change from the default form input name thus obfuscating that one is using spring security.
loginProcessingUrl() this seems to conflict with the custom logonHandler, but i think its req to handle the post and allow for spring to create a secure sesson.
defaultSucessUrl() tells spring where to go after successful logon (the post request).
failureUrl() defines the url for failed logon.
nowhere in my custom logon handler for the get request, are those settings in conflict... i think... but i've read the docs and the Spring Security 3 book and lots of online resources and i still do not feel as though i have a solid understanding of spring security... so i may be way off

Spring Boot application form validation is intercepted by /error page

Currently I am working on a project which used Spring Boot 1.2.7, and freemarker as page template engine.
I am trying to use Bean Validation as before, but it does not work as expected.
#RequestMapping(value = "/signup", method = RequestMethod.POST)
public String signup(#Valid #ModelAttribute("signup") SignupForm signup, BindingResult result) {
log.debug("signup form #" + signup);
if (result.hasErrors()) {
return "/signup";
}
//AccountDetails details = accountService.register(form);
return "redirect:/login";
}
When the bean validation is failed, it redirected to Spring Boot built-in /error page instead of displaying error messages in the signup page.
Your issue in SignupForm object and signup model attribute. Spring can not map both.
You need to redirect to signup page like :
#RequestMapping(value = "/signup", method = RequestMethod.POST)
public String signup(#Valid #ModelAttribute("signup") SignupForm signup, BindingResult result) {
log.debug("signup form #" + signup);
if (result.hasErrors()) {
return "signup";
}
//AccountDetails details = accountService.register(form);
return "redirect:/login";
}

Is it possible to change URL when returning ModelAndView from WEB-INF?

I'm using Spring MVC and I'm wondering is it possible to change URL when I return ModelAndView (the view is situated at the WEB-INF folder, so redirecting to it is not working) from the controller? I mean when I return it the URL is the previous one, and its obvious because dispatcher is working, not the redirecting.
#RequestMapping(value = "/login", method = RequestMethod.POST)
public ModelAndView authenticate(#RequestParam("login") String login, #RequestParam("password") String password) {
ModelAndView modelAndView = new ModelAndView();
User user = userDao.getUserByLogin(login);
if (user != null && user.getPassword().equals(password)) {
modelAndView.addObject("user", user);
modelAndView.setViewName("home");
}
return modelAndView;
}
So my home model is in WEB-INF folder, so return redirect:/home will not work for it. Yes, I can redirect it with return home, but in that case the URL will not change.
Use redirect:/url to some other method and return the view.
When redirecting the model attributes won't available in new method so to get that in redirected method set it in RedirectFlashAttributes.
Hope it helps.

Resources