Her*_*erb 5 java spring security-context
在我的春季应用程序中,我希望它SecurityContext始终拥有一个Authentication.如果它不是常规的UsernamePasswordAuthenticationToken,它将PreAuthenticatedAuthenticationToken描述"系统用户".这具有需要用户的不同系统功能的原因.如果没有用户上下文,为了避免特殊处理,我只想添加系统上下文.恕我直言,这也与单一责任原则有关.
为了实现这一点,我可以简单地实现我自己的SecurityContextHolderStrategy并将其设置为SecurityContextHolderwithSecurityContextHolder.setStrategyName(MyStrategyClassName);
现在来问题:
默认SecurityContextHolderStrategy是 ThreadLocalSecurityContextHolderStrategy.我很满意这个策略及其运作方式.我唯一要改变的是getContext()方法.
public SecurityContext getContext() {
SecurityContext ctx = CONTEXT_HOLDER.get();
if (ctx == null) {
ctx = createEmptyContext();
CONTEXT_HOLDER.set(ctx);
}
return ctx;
}
Run Code Online (Sandbox Code Playgroud)
至
public SecurityContext getContext() {
SecurityContext ctx = CONTEXT_HOLDER.get();
if (ctx == null) {
ctx = createEmptyContext();
Authentication authentication = new PreAuthenticatedAuthenticationToken("system", null);
authentication.setAuthenticated(true);
ctx.setAuthentication(authentication);
CONTEXT_HOLDER.set(ctx);
}
return ctx;
}
Run Code Online (Sandbox Code Playgroud)
这是不是可能的,因为ThreadLocalSecurityContextHolderStrategy类是没有public.当然我可以简单地复制粘贴ThreadLocalSecurityContextHolderStrategy到我自己的代码SecurityContextHolderStrategy并getContext()按照我想要的方式实现方法.但这给了我一种感觉,因为我可能走错了路.
我怎样才能将"系统用户" Authentication作为新的默认设置SecurityContext?
更新
我的上述方法显然不是解决方案,因为它极具侵入性,会产生冗余代码,需要在Web过滤器链中进行特殊处理.但它应该让我理解我的目标.我正在寻找一种解决方案,它尽可能地与原生弹簧安全实现无缝结合.我的问题是我对入侵方法非常关注.这怎么能很好地解决?我无法想象我是第一个有此要求的人.或者整个概念完全错了?
如果得到以下解决方案,它非常光滑并且不会碰撞或干扰任何东西。一般来说,我有两种情况需要进行null身份验证:
MODE_INHERITABLETHREADLOCAL根据用例通过配置解决,更多细节见下文。)解决方案1。
这仍然是主系统线程的问题。这很容易通过在系统启动时设置上下文来处理。此外,我将 配置SecurityContextHolder为使用 a,InheritableThreadLocalSecurityContextHolderStrategy因此所有子线程都将继承SecurityContext. 每次应用程序上下文刷新时,我们都会进行此设置。这允许@DirtiesContext在运行安全上下文相关测试时使用..
@Component
public class SecurityContextConfiguration {
@EventListener
public void setupSecurityContext(ContextRefreshedEvent event) {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
SecurityContextHolder.getContext().setAuthentication(new SystemAuthentication());
}
}
Run Code Online (Sandbox Code Playgroud)
解决方案2。
因为我已经配置了SecurityContextHolderMODE_INHERITABLETHREADLOCAL。预定线程将继承其父级Securitycontext。在我的用例中,这是不需要的,因为这意味着以下内容:如果计划任务通过用户操作进行初始化,它将在 users 下运行SecurityContext。由于我不想在系统重新启动时丢失计划任务,因此我将保留它们。这将导致在用户初始化之前的相同任务SecurityContext将SecurityContext在重新启动时初始化为系统。这会产生不一致。因此,我也配置了我的调度程序。
我只是将@Scheduled注释配置为DelegatingSecurityContextScheduledExecutorService允许我设置一个SecurityContext.
@EnableScheduling
@Configuration
public class SystemAwareSchedulerConfiguration implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
@Bean
public ScheduledExecutorService taskExecutor() {
ScheduledExecutorService delegateExecutor = Executors.newSingleThreadScheduledExecutor();
SecurityContext schedulerContext = createSchedulerSecurityContext();
return new DelegatingSecurityContextScheduledExecutorService(delegateExecutor, schedulerContext);
}
private SecurityContext createSchedulerSecurityContext() {
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(new SystemAuthentication());
return securityContext;
}
}
Run Code Online (Sandbox Code Playgroud)
使用这两种配置,如果 Web 容器未初始化线程,我将始终拥有 SystemUser 上下文。
| 归档时间: |
|
| 查看次数: |
2545 次 |
| 最近记录: |