SpringSecurity过滤器之SecurityContextPersistenceFilter

shigongp / 2023-05-03 / 原文

SecurityContextPersistenceFilter在请求之前从配置的SecurityContextRepository获得的信息填充SecurityContextHolder,并在请求完成并清除上下文holder后将其存储回存储库。默认情况下,它使用HttpSessionSecurityContextRepository。

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
		throws IOException, ServletException {
	// ensure that filter is only applied once per request
	if (request.getAttribute(FILTER_APPLIED) != null) {
		chain.doFilter(request, response);
		return;
	}
	request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
	if (this.forceEagerSessionCreation) {
		HttpSession session = request.getSession();
		if (this.logger.isDebugEnabled() && session.isNew()) {
			this.logger.debug(LogMessage.format("Created session %s eagerly", session.getId()));
		}
	}
	HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
	SecurityContext contextBeforeChainExecution = this.repo.loadContext(holder);
	try {
		SecurityContextHolder.setContext(contextBeforeChainExecution);
		if (contextBeforeChainExecution.getAuthentication() == null) {
			logger.debug("Set SecurityContextHolder to empty SecurityContext");
		}
		else {
			if (this.logger.isDebugEnabled()) {
				this.logger
						.debug(LogMessage.format("Set SecurityContextHolder to %s", contextBeforeChainExecution));
			}
		}
		chain.doFilter(holder.getRequest(), holder.getResponse());
	}
	finally {
		SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();
		// Crucial removal of SecurityContextHolder contents before anything else.
		SecurityContextHolder.clearContext();
		this.repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());
		request.removeAttribute(FILTER_APPLIED);
		this.logger.debug("Cleared SecurityContextHolder to complete request");
	}
}

在请求执行之前调用repo.loadContext加载SecurityContext并设置到SecurityContextHolder,之后可以通过SecurityContextHolder获取到SecurityContext,SecurityContext包装了鉴权对象(User对象和权限)。执行完后SecurityContextHolder清除SecurityContext,并保存SecurityContext,默认是保存到Session中。