Spring Security Web 5.1.2 源码解析 -- 框架缺省使用的页面重定向策略

本文深入探讨Spring Security框架中的重定向策略接口及其默认实现DefaultRedirectStrategy,详细讲解页面重定向的工作原理,包括如何处理相对URL和绝对URL,以及如何进行URL编码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

重定向策略接口定义

Spring Security Web 使用的页面重定向机制通过重定向策略接口定义:

package org.springframework.security.web;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Encapsulates the redirection logic for all classes in the framework which perform
 * redirects.
 * 面向框架内执行页面重定向的所有类封装重定向逻辑。
 *
 * @since 3.0
 */
public interface RedirectStrategy {

	/**
	 * Performs a redirect to the supplied URL 页面重定向到url
	 * @param request the current request 当前请求
	 * @param response the response to redirect 需要执行重定向的响应
	 * @param url the target URL to redirect to, for example "/login"
	 */
	void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
			throws IOException;
}

重定向策略缺省实现类

而整个框架内部,缺省使用了以上接口的实现类DefaultRedirectStrategy来执行相应的页面重定向任务:

package org.springframework.security.web;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.web.util.UrlUtils;

public class DefaultRedirectStrategy implements RedirectStrategy {

	protected final Log logger = LogFactory.getLog(getClass());

	// true 的话重定向URL要去掉协议部分,contex path部分,缺省为 false
	private boolean contextRelative;

	/**
	 * Redirects the response to the supplied URL.
	 * 重定向页面到指定的url
	 * 
	 * 如果属性 contextRelative为true,重定向值会是上下文路径`context path`之后的部分。
	 * 这样的话有可能导致重定向丢失协议信息,也就是HTTP/HTTPS部分,所以举例来讲,
	 * 如果你正在从HTTP跳转到HTTPS,这样做可能会导致问题。
	 */
	public void sendRedirect(HttpServletRequest request, HttpServletResponse response,
			String url) throws IOException {
		// 计算重定向url,主要是结合考虑属性 contextRelative
		String redirectUrl = calculateRedirectUrl(request.getContextPath(), url);
		// 编码重定向url,如果没有必要编码,会原值返回。
		// 这里的编码并不是指一般意义上的encodeURL(),而主要是考虑sessionID是否需要编码
		// 进URL。
		redirectUrl = response.encodeRedirectURL(redirectUrl);

		if (logger.isDebugEnabled()) {
			logger.debug("Redirecting to '" + redirectUrl + "'");
		}

		// 执行重定向
		response.sendRedirect(redirectUrl);
	}

	protected String calculateRedirectUrl(String contextPath, String url) {
		if (!UrlUtils.isAbsoluteUrl(url)) {
			// 如果 url 不是绝对路径URL,并且 contextRelative, 则直接返回该 url
			if (isContextRelative()) {
				return url;
			}
			else {
				// 如果 url 不是绝对路径URL,并且 contextRelative为false,
				// 则url前面附加上 contextPath 返回
				return contextPath + url;
			}
		}

		// Full URL, including http(s)://
		// url 是绝对路径url的情况, 也就是包含了 http(s)://协议部分的
		// 完整url路径
		if (!isContextRelative()) {
			// 绝对路径url的情况,如果 contextRelative 为 false, 则直接返回 url
			return url;
		}

		// Calculate the relative URL from the fully qualified URL, minus the last
		// occurrence of the scheme and base context.
		// 绝对路径url,并且 contextRelative  的情况,
		// 此时从url中取出协议部分,contextPath部分,contxtPath后面的/然后返回剩余部分
		url = url.substring(url.lastIndexOf("://") + 3); // strip off scheme
		url = url.substring(url.indexOf(contextPath) + contextPath.length());

		if (url.length() > 1 && url.charAt(0) == '/') {
			url = url.substring(1);
		}

		return url;
	}

	
	public void setContextRelative(boolean useRelativeContext) {
		this.contextRelative = useRelativeContext;
	}

	
	protected boolean isContextRelative() {
		return contextRelative;
	}
}

使用举例

  1. SimpleUrlAuthenticationFailureHandler
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
  1. SimpleUrlAuthenticationSuccessHandler/SimpleUrlLogoutSuccessHandler
    基类AbstractAuthenticationTargetUrlRequestHandler中:
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
  1. LoginUrlAuthenticationEntryPoint
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值