Spring Security核心组件之安全上下文

2022年6月2日14:07:55

1、安全上下文

Spring Security使用接口SecurityContext抽象建模"安全上下文"这一概念。这里安全上下文SecurityContext指的是当前执行线程使用的最少量的安全信息(其实就是用于代表访问者账号的有关信息)。

publicinterfaceSecurityContextextendsSerializable{AuthenticationgetAuthentication();voidsetAuthentication(Authentication authentication);}

Spring Security为接口SecurityContext提供的缺省实现SecurityContextImpl,该实现逻辑其实很简单,主要就是保持一个Authentication`对象

2、安全上下文管理器

当一个线程在服务用户期间,该安全上下文对象会保存在SecurityContextHolder中。

publicclassSecurityContextHolder{publicstaticfinalString MODE_THREADLOCAL="MODE_THREADLOCAL";publicstaticfinalString MODE_INHERITABLETHREADLOCAL="MODE_INHERITABLETHREADLOCAL";publicstaticfinalString MODE_GLOBAL="MODE_GLOBAL";publicstaticfinalString SYSTEM_PROPERTY="spring.security.strategy";privatestaticString strategyName=System.getProperty(SYSTEM_PROPERTY);privatestaticSecurityContextHolderStrategy strategy;//默认是ThreadLocalSecurityContextHolderStrategyprivatestaticint initializeCount=0;static{initialize();}//忽略代码....privatestaticvoidinitialize(){if(!StringUtils.hasText(strategyName)){// Set default
			strategyName= MODE_THREADLOCAL;}if(strategyName.equals(MODE_THREADLOCAL)){
			strategy=newThreadLocalSecurityContextHolderStrategy();}elseif(strategyName.equals(MODE_INHERITABLETHREADLOCAL)){
			strategy=newInheritableThreadLocalSecurityContextHolderStrategy();}elseif(strategyName.equals(MODE_GLOBAL)){
			strategy=newGlobalSecurityContextHolderStrategy();}else{// Try to load a custom strategytry{Class<?> clazz=Class.forName(strategyName);Constructor<?> customStrategy= clazz.getConstructor();
				strategy=(SecurityContextHolderStrategy) customStrategy.newInstance();}catch(Exception ex){ReflectionUtils.handleReflectionException(ex);}}

		initializeCount++;}//忽略代码....}

SecurityContextHolder类提供的功能是保持SecurityContext,不过它的用法不是让使用者创建多个SecurityContextHolder对象,而是提供一组公开静态工具方法。其底层是感觉系统变量spring.security.strategy的值来判断使用何种策略SecurityContextHolderStrategy

SecurityContextHolder 类有2种方式初始化 SecurityContextHolderStrategy。

其一,通过其静态方法setStrategyName。

publicstaticvoidsetStrategyName(String strategyName){SecurityContextHolder.strategyName= strategyName;initialize();}

其二,通过设置属性值 spring.security.strategy。

publicstaticfinalString SYSTEM_PROPERTY="spring.security.strategy";privatestaticString strategyName=System.getProperty(SYSTEM_PROPERTY);

3、安全上下文生成器

publicinterfaceSecurityContextHolderStrategy{voidclearContext();SecurityContextgetContext();voidsetContext(SecurityContext context);SecurityContextcreateEmptyContext();}

Spring Security核心组件之安全上下文
线程本地模式

对应用中的某个线程保持一个SecurityContext,这种模式下,应用中的每个线程同一时间通过SecurityContextHolder访问到的都是关于自己线程的SecurityContext;

finalclassThreadLocalSecurityContextHolderStrategyimplementsSecurityContextHolderStrategy{//使用ThreadLocal存储安全上下文privatestaticfinalThreadLocal<SecurityContext> contextHolder=newThreadLocal<>();publicvoidclearContext(){
		contextHolder.remove();}publicSecurityContextgetContext(){SecurityContext ctx= contextHolder.get();if(ctx==null){
			ctx=createEmptyContext();
			contextHolder.set(ctx);}return ctx;}publicvoidsetContext(SecurityContext context){Assert.notNull(context,"Only non-null SecurityContext instances are permitted");
		contextHolder.set(context);}publicSecurityContextcreateEmptyContext(){returnnewSecurityContextImpl();}}

线程继承模式

InheritableThreadLocal 相较于 ThreadLocal,多了子线程可以继承父线程的属性的特性,但是,针对普通WEB应用,应该是英雄无用武之地。

finalclassInheritableThreadLocalSecurityContextHolderStrategyimplementsSecurityContextHolderStrategy{privatestaticfinalThreadLocal<SecurityContext> contextHolder=newInheritableThreadLocal<>();//忽略代码.....}

全局模式

对整个应用公开保持一个SecurityContext,这种模式下,应用中的多个线程同一时间通过SecurityContextHolder访问到的都会是同一个SecurityContext对象;

finalclassGlobalSecurityContextHolderStrategyimplementsSecurityContextHolderStrategy{privatestaticSecurityContext contextHolder;publicvoidclearContext(){
		contextHolder=null;}publicSecurityContextgetContext(){if(contextHolder==null){
			contextHolder=newSecurityContextImpl();}return contextHolder;}publicvoidsetContext(SecurityContext context){Assert.notNull(context,"Only non-null SecurityContext instances are permitted");
		contextHolder= context;}publicSecurityContextcreateEmptyContext(){returnnewSecurityContextImpl();}}

4、安全上下文生成器的自定义

publicclassMySecurityContextHolderStrategyimplementsSecurityContextHolderStrategy{privatestaticfinalThreadLocal<SecurityContext> contextHolder=newThreadLocal<>();publicvoidclearContext(){
        contextHolder.remove();}publicSecurityContextgetContext(){SecurityContext ctx= contextHolder.get();if(ctx==null){
            ctx=createEmptyContext();
            contextHolder.set(ctx);}return ctx;}publicvoidsetContext(SecurityContext context){Assert.notNull(context,"Only non-null SecurityContext instances are permitted");
        contextHolder.set(context);}publicSecurityContextcreateEmptyContext(){returnnewSecurityContextImpl();}}

MySecurityContextHolderStrategy的注册

@ConfigurationpublicclassMyWebSecurityConfigextendsWebSecurityConfigurerAdapter{static{SecurityContextHolder.setStrategyName("learinning.securityextend.MySecurityContextHolderStrategy");}//忽略代码....}

测试

@RestController@RequestMapping("demo")publicclassDemoController{@GetMapping("test")// @RolesAllowed({"admin"})publicStringtest1(){SecurityContextHolderStrategy context=SecurityContextHolder.getContextHolderStrategy();return"test1";}}

Spring Security核心组件之安全上下文

  • 作者:这是一条海鱼
  • 原文链接:https://blog.csdn.net/qq_41071876/article/details/122290308
    更新时间:2022年6月2日14:07:55 ,共 5042 字。