SmartRedirectStrategy.java
- package cn.home1.oss.lib.security.internal.template;
- import static java.lang.Boolean.FALSE;
- import static java.lang.Boolean.TRUE;
- import static org.apache.commons.lang3.StringUtils.isNotBlank;
- import cn.home1.oss.lib.common.CodecUtils;
- import lombok.SneakyThrows;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.security.web.RedirectStrategy;
- import org.springframework.security.web.util.UrlUtils;
- import java.io.IOException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- /**
- * Created by zhanghaolun on 16/11/11.
- */
- @Slf4j
- public class SmartRedirectStrategy implements RedirectStrategy {
- public static final String PARAM_REDIRECT = "redirect";
- private boolean contextRelative;
- /**
- * Redirects the response to the supplied URL.
- * <p>
- * If <tt>contextRelative</tt> is set, the redirect value will be the value after the
- * request context path. Note that this will result in the loss of protocol
- * information (HTTP or HTTPS), so will cause problems if a redirect is being
- * performed to change to HTTPS, for example.
- * </p>
- */
- @Override
- public void sendRedirect( //
- final HttpServletRequest request,
- final HttpServletResponse response,
- final String url //
- ) throws IOException {
- String redirectUrl = buildRedirectUrl(request, url);
- redirectUrl = response.encodeRedirectURL(redirectUrl);
- if (log.isDebugEnabled()) {
- log.debug("Redirecting to '" + redirectUrl + "'");
- }
- response.sendRedirect(redirectUrl);
- }
- private String buildRedirectUrl( //
- final HttpServletRequest request, //
- final String url //
- ) {
- final String redirectUrl = calculateRedirectUrl(request, url);
- final String requestUrl = request.getRequestURL().toString();
- final String paramValue = request.getParameter(PARAM_REDIRECT);
- final Boolean containsRedirectParam = containsParam(requestUrl, PARAM_REDIRECT) || isNotBlank(paramValue);
- final String result;
- if (containsRedirectParam) {
- result = appendParam(redirectUrl, PARAM_REDIRECT, paramValue);
- } else {
- result = redirectUrl;
- }
- return result;
- }
- private String calculateRedirectUrl(final HttpServletRequest request, final String url) {
- final String contextPath = request.getContextPath();
- final String redirectUrl;
- if (!UrlUtils.isAbsoluteUrl(url)) {
- if (this.contextRelative) {
- redirectUrl = url;
- } else {
- redirectUrl = contextPath + url;
- }
- } else {
- // Full URL, including http(s)://
- if (!this.contextRelative) {
- redirectUrl = url;
- } else {
- // Calculate the relative URL from the fully qualified URL, minus the last
- // occurrence of the scheme and base context.
- final String withoutScheme = url.substring(url.lastIndexOf("://") + 3); // strip off scheme
- final String withoutContextPath = withoutScheme.substring( //
- withoutScheme.indexOf(contextPath) + contextPath.length());
- if (withoutContextPath.length() > 1 && withoutContextPath.charAt(0) == '/') {
- redirectUrl = url.substring(1);
- } else {
- redirectUrl = withoutContextPath;
- }
- }
- }
- return redirectUrl;
- }
- /**
- * If <tt>true</tt>, causes any redirection URLs to be calculated minus the protocol
- * and context path (defaults to <tt>false</tt>).
- *
- * @param useRelativeContext useRelativeContext
- */
- public void setContextRelative(final boolean useRelativeContext) {
- this.contextRelative = useRelativeContext;
- }
- public static Boolean containsParam(final String url, final String paramName) {
- Boolean containsParam = FALSE;
- if (isNotBlank(url) && url.contains("?")) { // find redirect param
- final String queryString = url.substring(url.indexOf('?') + 1);
- final String[] params = queryString.split("&");
- for (final String param : params) {
- final String name = param.split("=")[0];
- if (paramName.equals(name)) {
- containsParam = TRUE;
- break;
- }
- }
- }
- return containsParam;
- }
- @SneakyThrows
- public static String appendParam(final String url, final String paramName, final String paramValue) {
- final String param = paramName + "=" + CodecUtils.urlEncode(paramValue);
- final String result;
- if (url != null) {
- if (url.contains("?")) {
- result = url + "&" + param;
- } else {
- result = url + "?" + param;
- }
- } else {
- result = null;
- }
- return result;
- }
- }