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();}
线程本地模式
对应用中的某个线程保持一个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";}}
热门文章
- 动物医院大众点评文案范文图片(动物医院大众点评100字通用评论)
- 2月27日 | 最新V2ray/SSR/Shadowrocket/Clash高速免费节点,最高速度20.3M/S 免费Clash机场订阅地址
- 2月18日 | 最新Clash/Shadowrocket/SSR/V2ray高速免费节点,最高速度18.1M/S 免费Clash机场订阅地址
- 附近的动物医院在哪里啊(附近哪有动物医院?)
- 1月18日 | 最新Clash/V2ray/Shadowrocket/SSR高速免费节点,最高速度19.9M/S 免费Clash机场订阅地址
- 太原哪里批发狗粮(太原哪里有批发狗粮的地方?)
- 2月23日 | 最新Shadowrocket/Clash/V2ray/SSR高速免费节点,最高速度22.1M/S 免费Clash机场订阅地址
- 动物打疫苗去哪打(动物打疫苗去哪打的)
- 动物疫苗间隔时间多长打一次比较好(动物疫苗多长时间内打)
- 宠物领养协议是啥意思啊怎么写呀(宠物的领养协议是有法律保护的吗)