/* * Copyright (C) 2013-2017 NTT DATA Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.terasoluna.gfw.security.web.redirect; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.core.Authentication; import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.RedirectStrategy; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.util.StringUtils; /** * Default transition destination after a successful login is specified by {@code default-target-url} attribute. This class * changes the default transition destination to a path received as a request parameter. <br> * <p> * This functionality is to be used when there is a need to transition to a different location rather than the one specified in * {@code default-target-url}<br> * To use this functionality, transition destination path must be added in the request parameter of the screen from which * transition to login screen is done, as well as the login screen.<br> * Using the transition destination path received from the login screen, redirect is executed. * <p> * Attribute name of request parameter is set to {@code redirectTo} by default. However, it can be changed by explicitly it in * the {@code targetUrlParameter}.<br> * <p> * Since, this functionality does a {@code javax.servlet.http.HttpServletResponse#sendRedirect(String)} after successful login. * {@code sendRedirect()} creates a new {@code HttServletRequest} of type {@code GET} is created. Hence, transition destination * path should correspond to a {@code GET} request handler. <br> * . * <p> * This functionality can be used in a situation where search screen -> detail screen is possible without login. but login is * required for any update process on the detail screen. In this case, it should transition back to the detail screen after * login <br> * Usage Example is as below: * </p> * <h3>Example of Spring Security Configuration</h3> * * <pre> * <http auto-config="true"> * .... * <form-login login-page="/login" default-target-url="/" * always-use-default-target="false" * <strong style=color:red>authentication-failure-handler-ref="redirectErrorHandler" * authentication-success-handler-ref="redirectHandler"</strong> /> * .... * </http> * * <beans:bean id="redirectHandler" * class="org.terasoluna.gfw.security.web.redirect.RedirectAuthenticationHandler"/> * * <beans:bean id="redirectErrorHandler" * class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> * <beans:property name="defaultFailureUrl" value="/login?error=true"/> * <strong style=color:red><beans:property name="useForward" value="true"/></strong> * </beans:bean> * </pre> * * Specify {@code org.terasoluna.gfw.web.security.RedirectAuthenticationHandler} as the handler class at the time of successful * authentication in {@code authentication-success-handler-ref}<br> * Specify {@code org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler} as the handler class at * the time of failed authentication in {@code authentication-failure-handler-ref}<br> * At the time of failed authentication, redirect is done by default. In case of a redirect, a new {@code HttpServletRequest} is * created and the existing one is lost. Hence in order to change this behavior from redirect to forward for preserving the * existing request, a handler is needed to be specified for failed authentication also.<br> * In the bean definition for {@code org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler}, * {@code true} needs to be specified for {@code useForward} attribute. By doing this, redirect gets changed to forward<br> * Further, path of login screen must be specified in {@code defaultFailureUrl}<br> * <h3>Example of Transition Source Screen</h3> * * <pre> * <form:form action="${pageContext.request.contextPath}/login" method="get" cssClass="inline" > * <input type="submit" value="login"> * <strong style=color:red><input type="hidden" name="redirectTo" * value="${pageContext.request.contextPath}/user/read?userCode=${f:h(param.userCode)}" /></strong> * </form:form> * </pre> * * In order to go to login page, specify the path of login screen as a hidden input field. <h3>Example of Login Screen</h3> * * <pre> * <input type="submit" value="login" /> * <input type="hidden" name="redirectTo" value="${f:h(param.redirectTo)}" /> * </pre> * * The value received from transition source screen is again set to {@code hidden} field<br> * In this example, redirect is done to following path {@code /user/read?userCode=$ f:h(param.userCode)} * @deprecated This feature is expected to replace the alternative functions that will be provided by Spring Security. Until the * function is provided , Use * {@link org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler} . */ @Deprecated public class RedirectAuthenticationHandler extends SavedRequestAwareAuthenticationSuccessHandler implements InitializingBean { /** * RedirectStrategy to use if redirect path is specified as a request parameter. (default:"redirectTo") */ private RedirectStrategy targetUrlParameterRedirectStrategy; /** * Constructor. <br> */ public RedirectAuthenticationHandler() { super.setTargetUrlParameter("redirectTo"); } /** * set RedirectStrategy to use if redirect path is specified as a request parameter. (default:"redirectTo")<br> * @param redirectToRedirectStrategy RedirectStrategy to use if redirect path is specified as a request parameter */ public void setRedirectToRedirectStrategy( RedirectStrategy redirectToRedirectStrategy) { this.targetUrlParameterRedirectStrategy = redirectToRedirectStrategy; } /** * Performs redirect<br> * <p> * If there is no redirect path specified as a request parameter, redirects to default path * @param request current HTTP request * @param response current HTTP response * @param authentication Authentication information of spring security * @see org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler#onAuthenticationSuccess */ @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { String targetUrlParameter = getTargetUrlParameter(); if (targetUrlParameter != null && targetUrlParameterRedirectStrategy != null) { String redirectUrl = request.getParameter(targetUrlParameter); if (StringUtils.hasText(redirectUrl)) { clearAuthenticationAttributes(request); targetUrlParameterRedirectStrategy.sendRedirect(request, response, redirectUrl); return; } } super.onAuthenticationSuccess(request, response, authentication); } /** * If {@link RedirectStrategy} is not externally set, {@link DefaultRedirectStrategy} is used. * <p> * {@code contextRelative} property of DefaultRedirectStrategy is set to true.<br> * In order to set it to {@code false}, {@code targetUrlParameterRedirectStrategy} property <br> * must be set in the bean definition <br> * </p> * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ @Override public void afterPropertiesSet() { if (targetUrlParameterRedirectStrategy == null) { // set contextRelative=true as default RedirectStrategy targetUrlParameterRedirectStrategy = new DefaultRedirectStrategy(); ((DefaultRedirectStrategy) targetUrlParameterRedirectStrategy) .setContextRelative(true); } } }