SpringSecurity源码解析--SecurityContextPersistenceFilter

概述

SecurityContextPersistenceFilter有两个主要任务:

  1. 在请求到达时处理之前,从SecurityContextRepository中获取安全上下文信息填充到SecurityContextHolder;
  2. 在请求处理结束后返回响应时,将SecurityContextHolder中的安全上下文信息保存回SecurityContextRepository,并清空SecurityContextHolder。

通过SecurityContextPersistenceFilter的这种机制,在整个请求处理过程中,开发人员都可以通过使用SecurityContextHolder获取当前访问用户的安全上下文信息。

缺省情况下,SecurityContextPersistenceFilter使用的SecurityContextRepository是HttpSessionSecurityContextRepository,也就是将安全上下文的信息保存在用户的会话中。

为了解决不同Serlvet容器上,尤其是weblogic上的兼容性问题,此Filter必须在整个request处理过程中被调用最多一次。

该Filter也必须在任何认证机制逻辑发生之前被调用。因为这些认证机制都依赖于SecurityContextHolder所包含的安全上下文对象。

public class SecurityContextPersistenceFilter extends GenericFilterBean {

	// 确保该Filter在一个request处理过程中最多被调到用一次的机制:
	// 一旦该Fitler被调用过,他会在当前request增加该属性值为true,利用此标记
	// 可以避免Filter被调用二次。
	static final String FILTER_APPLIED = "__spring_security_scpf_applied";

	// 安全上下文存储库
	private SecurityContextRepository repo;

	private boolean forceEagerSessionCreation = false;

	public SecurityContextPersistenceFilter() {
		// 缺省使用http session 作为安全上下文对象存储
		this(new HttpSessionSecurityContextRepository());
	}

	public SecurityContextPersistenceFilter(SecurityContextRepository repo) {
		this.repo = repo;
	}

	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;

		if (request.getAttribute(FILTER_APPLIED) != null) {
			// ensure that filter is only applied once per request
			// 检查调用标志,如果request上已经存在属性FILTER_APPLIED,
			// 表明该Filter在该request的处理过程中已经被调用过
			chain.doFilter(request, response);
			return;
		}

		final boolean debug = logger.isDebugEnabled();

		// 设置该Filter已经被调用的标记
		request.setAttribute(FILTER_APPLIED, Boolean.TRUE);

		if (forceEagerSessionCreation) {
			HttpSession session = request.getSession();

			if (debug && session.isNew()) {
				logger.debug("Eagerly created session: " + session.getId());
			}
		}

		HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request,
				response);
		// 从安全上下文存储库(缺省是http session)中读取安全上下文对象		
		SecurityContext contextBeforeChainExecution = repo.loadContext(holder);

		try {
			// 设置安全上下文对象到SecurityContextHolder然后才继续Filter chain的调用
			SecurityContextHolder.setContext(contextBeforeChainExecution);

			chain.doFilter(holder.getRequest(), holder.getResponse());

		}
		finally {
			SecurityContext contextAfterChainExecution = SecurityContextHolder
					.getContext();
			// Crucial removal of SecurityContextHolder contents - do this before anything
			// else.
			// 当前请求已经被处理完成了,清除SecurityContextHolder并将最新的
			// 安全上下文对象保存回安全上下文存储库(缺省是http session)
			SecurityContextHolder.clearContext();
			repo.saveContext(contextAfterChainExecution, holder.getRequest(),
					holder.getResponse());
			request.removeAttribute(FILTER_APPLIED);

			if (debug) {
				logger.debug("SecurityContextHolder now cleared, as request processing completed");
			}
		}
	}

	public void setForceEagerSessionCreation(boolean forceEagerSessionCreation) {
		this.forceEagerSessionCreation = forceEagerSessionCreation;
	}
}


其他过滤器总和

SpringSecurity过滤器清单

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值