Customizing behavior after login
We have already discussed how to customize a user's experience during login, but sometimes it is necessary to customize the behavior after login. In this section, we will discuss how Spring Security behaves after login and will provide a simple mechanism to customize this behavior.
In the default configuration, Spring Security has two different flows after successful authentication. The first scenario occurs if a user never visits a resource that requires authentication. In this instance, after a successful login attempt, the user will be sent to the defaultSuccessUrl() method chained to the formLogin() method. If left undefined, defaultSuccessUrl() will be the context root of the application.
If a user requests a protected page before being authenticated, Spring Security will remember the last protected page that was accessed prior to authenticating, using o.s.s.web.savedrequest.RequestCache. Upon successful authentication, Spring Security will send the user to the last protected page that was accessed prior to authentication. For example, if an unauthenticated user requests the My Events page, they will be sent to the Login page.
After successful authentication, they will be sent to the previously requested My Events page.
A common requirement is to customize Spring Security to send the user to a different defaultSuccessUrl() method, depending on the user's role. Let's take a look at how this can be accomplished by performing the following steps:
- The first step is to configure the defaultSuccessUrl() method chained after the formLogin() method. Go ahead and update the security.xml file to use /default instead of the context root:
//src/main/java/com/packtpub/springsecurity/configuration/
SecurityConfig.java
.formLogin()
.loginPage("/login/form")
.loginProcessingUrl("/login")
.failureUrl("/login/form?error")
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/default")
.permitAll()
- The next step is to create a controller that processes /default. In the following code, you will find a sample Spring MVC controller, DefaultController, which demonstrates how to redirect administrators to the All Events page and other users to the Welcome page. Create a new file in the following location:
//src/main/java/com/packtpub/springsecurity/web/controllers/
DefaultController.java
// imports omitted
@Controller
public class DefaultController {
@RequestMapping("/default")
public String defaultAfterLogin(HttpServletRequest request) {
if (request.isUserInRole("ADMIN")) {
return "redirect:/events/";
}
return "redirect:/";
}
}
In Spring Tool Suite, you can use Shift + Ctrl + O to automatically add the missing imports.
There are a few things to point out about DefaultController and how it works. The first is that Spring Security makes the HttpServletRequest parameter aware of the currently logged-in user. In this instance, we are able to inspect which role the user belongs to without relying on any of Spring Security's APIs. This is good because if Spring Security's APIs change or we decide we want to switch our security implementation, we have less code that needs to be updated. It should also be noted that while we implement this controller with a Spring MVC controller, our defaultSuccessUrl() method can be handled by any controller implementation (for example, Struts, a standard servlet, and so on) if we desire.
- If you wish to always go to the defaultSuccessUrl() method, you can leverage the second parameter to the defaultSuccessUrl() method, which is a Boolean for always use. We will not do this in our configuration, but you can see an example of it as follows:
.defaultSuccessUrl("/default", true)
- You are now ready to give it a try. Restart the application and go directly to the My Events page, then log in; you will see that you are on the My Events page.
- Next, log out and try logging in as user1@example.com.
- You should be on the Welcome page. Log out and log in as admin1@example.com, and you will be
sent to the All Events page.
Your code should now look like chapter02.06-calendar.