• 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();
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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);
    		}
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    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);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    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;
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    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);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    如何避免资源管理陷阱
    各类经典VRP,车间调度问题,组合优化问题基准测试集Benchmark
    【JAVA反射】Method类
    SD-WAN让跨境网络访问更快、更安全!
    Android音视频开发-AudioTrack
    关于Oracle数据库字段排序的问题
    虚拟摄像头之九: IMX8Q 的 camera.imx8.hal 框架详解
    Spring Boot 自定义注解
    洛谷千题详解 | P1018 [NOIP2000 提高组] 乘积最大【C++、Python、Java、pascal语言】
    支持导入 Eolink 插件,别小看这个开源 API 管理工具了
  • 原文地址:https://blog.csdn.net/moernagedian/article/details/137914344