Reputation: 17085
I am building a website that has 2 pages. A recipe list page, a recipe detail page, and a sign in page. A user can sign in to the website by clicking on a sign in button on the recipe list page or recipe detail page. When a user click the sign in button, the user will be brought to the sign in page. I would like to redirect the user back again to the recipe detail page if they click the sign in button from the recipe detail page, or to the recipe list page if they click the sign in button from the recipe list page.
I wrote this method in a Controller class. This method will be called whenever user sign in to the website. I stored the referer URL into the session. The intention of saving this URL into a session is to keep track the page where user click on the sign in button. And also to redirect user to that page in the authentication handler that I wrote.
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String openLoginPage(Model uiModel, HttpServletRequest request) {
String referrer = request.getHeader("Referer");
request.getSession().setAttribute("url_prior_login", referrer);
return RECIPE_LOGIN_PAGE;
}
I also created an authentication handler class called SuccessHandler
.
public class SuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
/*
* (non-Javadoc)
*
* @see org.springframework.security.web.authentication.
* SavedRequestAwareAuthenticationSuccessHandler
* #onAuthenticationSuccess(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse,
* org.springframework.security.core.Authentication)
*/
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
String url = (String) request.getSession().getAttribute("url_prior_login");
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal != null && principal instanceof RecipeUser) {
request.getSession().setAttribute("RecipeUser", (RecipeUser) principal);
}
getRedirectStrategy().sendRedirect(request, response, url);
}
}
This class will redirect user to either the recipe list page or the recipe detail page when they sign in to the website. I register this class inside a security-context.xml
file:
<http use-expressions="true" auto-config="false" entry-point-ref="authenticationEntryPoint">
<intercept-url pattern="/login" access="permitAll" />
<form-login login-page="/login" authentication-failure-url="/loginfail"
default-target-url="/login"
authentication-success-handler-ref="successHandler" />
<logout logout-success-url="/" />
</http>
<authentication-manager alias="authManager">
<authentication-provider user-service-ref='myUserDetailsService' />
</authentication-manager>
<beans:bean id="myUserDetailsService" class="com.safe.stack.service.security.UserService">
<beans:property name="dataSource" ref="dataSource" />
</beans:bean>
<beans:bean id="successHandler"
class="com.safe.stack.service.security.SuccessHandler" />
<beans:bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login"/>
</beans:bean>
Is this a good way to do what I want to achieve ? Is there a better way to do this ? I could not find any example on how to this using Spring MVC.
Thank you
Upvotes: 3
Views: 6835
Reputation: 3189
This is how I do it in Spring 3.1.4
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
// Supplies the default target Url that will be used if
// no saved request is found in the session
setDefaultTargetUrl("/member/dashboard");
super.onAuthenticationSuccess(request, response, authentication);
}
Extending SavedRequestAwareAuthenticationSuccessHandler
is correct since the redirection is done automatically.
Upvotes: 1
Reputation: 438
Just add new attribute "always-use-default-target" to "form-login" tag and set it to "false" (by default it is set to "true", even if don't specify it) like this:
<form-login
login-page="/login" authentication-failure-url="/loginfail"
default-target-url="/login"
authentication-success-handler-ref="successHandler"
always-use-default-target="false"
/>
You can read more about it in Spring Security documentation here, on end of section: 3.2.3.
If you add this, you won't need custom onAuthenticationSuccess anymore and you won't need to store anything in session on login page.
Upvotes: 0