SpringSecurity源码4-安全上下文

SecurityContext.class
当前线程关联的最小安全信息,提供Authentication的get/set方法,实际上就是存储"当前用户"账号信息和相关权限。

在这里插入图片描述

SecurityContextHolder.class
SecurityContext的持有器

	// 全部委托给策略类
	public static void setContext(SecurityContext context) {
		strategy.setContext(context);
	}
	public static SecurityContext getContext() {
		return strategy.getContext();
	}
	public static void clearContext() {
		strategy.clearContext();
	}

SecurityContextHolderStrategy.class
用于针对线程存储安全上下文信息的策略。

在这里插入图片描述
核心实现类ThreadLocalSecurityContextHolderStrategy
在这里插入图片描述

ThreadLocalSecurityContextHolderStrategy.class
基于ThreadLocal 的实现SecurityContextHolderStrategy。
在这里插入图片描述

回到SecurityContextHolder.class方法

	static {
		initialize();
	}

	private static void initialize() {
		initializeStrategy();
		initializeCount++;
	}
	
	private static void initializeStrategy() {
		if (MODE_PRE_INITIALIZED.equals(strategyName)) {
			Assert.state(strategy != null, "When using " + MODE_PRE_INITIALIZED
					+ ", setContextHolderStrategy must be called with the fully constructed strategy");
			return;
		}
		// 默认的话就是上文提到的ThreadLocalSecurityContextHolderStrategy
		if (!StringUtils.hasText(strategyName)) {
			// Set default
			strategyName = MODE_THREADLOCAL;
		}
		if (strategyName.equals(MODE_THREADLOCAL)) {
			strategy = new ThreadLocalSecurityContextHolderStrategy();
			return;
		}
		if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) {
			strategy = new InheritableThreadLocalSecurityContextHolderStrategy();
			return;
		}
		if (strategyName.equals(MODE_GLOBAL)) {
			strategy = new GlobalSecurityContextHolderStrategy();
			return;
		}
		// Try to load a custom strategy
		try {
			Class<?> clazz = Class.forName(strategyName);
			Constructor<?> customStrategy = clazz.getConstructor();
			strategy = (SecurityContextHolderStrategy) customStrategy.newInstance();
		}
		catch (Exception ex) {
			ReflectionUtils.handleReflectionException(ex);
		}
	}

SecurityContextRepository.class
用于在请求之间持久保存的策略 SecurityContext
可以通过redis实现单点登录问题

public interface SecurityContextRepository {

	// 废弃
	@Deprecated
	SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder);

	
	default Supplier<SecurityContext> loadContext(HttpServletRequest request) {
		return SingletonSupplier.of(() -> loadContext(new HttpRequestResponseHolder(request, null)));
	}

	void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response);

	boolean containsContext(HttpServletRequest request);

}

SecurityContextHolderFilter.class
使用 获取 SecurityContextRepository SecurityContext 并将其设置在 SecurityContextHolder上的 的 。javax.servlet.Filter这与 类似SecurityContextPersistenceFilter,只是必须显式调用 来SecurityContextRepository.saveContext(SecurityContext, HttpServletRequest, HttpServletResponse)保存 SecurityContext.这提高了效率,并通过允许不同的身份验证机制单独选择是否应保留身份验证来提供更好的灵活性。



public class SecurityContextHolderFilter extends OncePerRequestFilter {

	private final SecurityContextRepository securityContextRepository;

	private boolean shouldNotFilterErrorDispatch;

	/**
	 * Creates a new instance.
	 * @param securityContextRepository the repository to use. Cannot be null.
	 */
	public SecurityContextHolderFilter(SecurityContextRepository securityContextRepository) {
		Assert.notNull(securityContextRepository, "securityContextRepository cannot be null");
		this.securityContextRepository = securityContextRepository;
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
		SecurityContext securityContext = this.securityContextRepository.loadContext(request).get();
		try {
			SecurityContextHolder.setContext(securityContext);
			filterChain.doFilter(request, response);
		}
		finally {
			SecurityContextHolder.clearContext();
		}
	}

	@Override
	protected boolean shouldNotFilterErrorDispatch() {
		return this.shouldNotFilterErrorDispatch;
	}

	public void setShouldNotFilterErrorDispatch(boolean shouldNotFilterErrorDispatch) {
		this.shouldNotFilterErrorDispatch = shouldNotFilterErrorDispatch;
	}

}

OncePerRequestFilter .class
每次请求只执行一次filter

SecurityContextConfigurer.class

在这里插入图片描述

@Override
	@SuppressWarnings("unchecked")
	public void configure(H http) {
		SecurityContextRepository securityContextRepository = getSecurityContextRepository();
		if (this.requireExplicitSave) {
			SecurityContextHolderFilter securityContextHolderFilter = postProcess(
					new SecurityContextHolderFilter(securityContextRepository));
			http.addFilter(securityContextHolderFilter);
		}
		else {
		// 由框架帮你去构建filter
			SecurityContextPersistenceFilter securityContextFilter = new SecurityContextPersistenceFilter(
					securityContextRepository);
			SessionManagementConfigurer<?> sessionManagement = http.getConfigurer(SessionManagementConfigurer.class);
			SessionCreationPolicy sessionCreationPolicy = (sessionManagement != null)
					? sessionManagement.getSessionCreationPolicy() : null;
			if (SessionCreationPolicy.ALWAYS == sessionCreationPolicy) {
				securityContextFilter.setForceEagerSessionCreation(true);
				http.addFilter(postProcess(new ForceEagerSessionCreationFilter()));
			}
			securityContextFilter = postProcess(securityContextFilter);
			http.addFilter(securityContextFilter);
		}
	}
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值