36.2 DelegatingSecurityContextExecutor委托安全上下文执行器

在前一节中,我们发现使用delegatingsecuritytycontextrunable很容易,但这并不理想,因为我们必须了解Spring Security才能使用它。让我们看一下DelegatingSecurityContextExecutor如何保护我们的代码免受我们使用的任何Spring Security知识的影响。

DelegatingSecurityContextExecutor的设计与delegatingsecuritycontextrunable的设计非常相似,只是它接受委托执行器Executor 而不是委托可运行Runnable,。您可以在下面看到如何使用它的示例:

 1 SecurityContext context = SecurityContextHolder.createEmptyContext();
 2 Authentication authentication = new UsernamePasswordAuthenticationToken("user","doesnotmatter", AuthorityUtils.createAuthorityList("ROLE_USER"));
 4 context.setAuthentication(authentication);
 5 
 6 SimpleAsyncTaskExecutor delegateExecutor = new SimpleAsyncTaskExecutor();
 8 DelegatingSecurityContextExecutor executor = new DelegatingSecurityContextExecutor(delegateExecutor, context);
10 
11 Runnable originalRunnable = new Runnable() {
12   public void run() {
13     // invoke secured service
14   }
15 };
16 
17 executor.execute(originalRunnable);

该代码执行以下步骤:

  创建要用于我们的委托的安全上下文。请注意,在本例中,我们只是手工创建了SecurityContext。然而,我们从哪里或如何获得安全上下文并不重要(即,如果我们愿意,我们可以从安全上下文持有者那里获得它)。

  创建一个委托执行器,负责执行提交的Runnables

  最后,我们创建了一个DelegatingSecurityContextExecutor,它负责包装任何传递到带有delegatingsecuritycontextrunable的执行方法中的Runnable。然后,它将包装好的可运行Runnable 对象传递给委托执行器delegateExecutor。在这种情况下,相同的安全上下文将用于提交给我们的DelegatingSecurityContextExecutor的每个可运行文件。如果我们正在运行后台任务,而这些任务需要由拥有更高权限的用户来运行,这就很好了

  此时,您可能会问自己“这是如何保护我的代码不了解Spring Security的?”我们不需要在自己的代码中创建SecurityContext和DelegatingSecurityContextExecutor,而是可以注入一个已经初始化的DelegatingSecurityContextExecutor实例。

 1 @Autowired
 2 private Executor executor; // becomes an instance of our DelegatingSecurityContextExecutor
 3 
 4 public void submitRunnable() {
 5 Runnable originalRunnable = new Runnable() {
 6     public void run() {
 7     // invoke secured service
 8     }
 9 };
10 executor.execute(originalRunnable);
11 }

现在,我们的代码不知道安全上下文SecurityContext 正在被传播到线程,然后执行originalRunnable ,然后清除安全上下文持有者SecurityContextHolder 。在这个例子中,相同的用户被用来执行每个线程。如果我们在调用executor.execute(Runnable)时想使用SecurityContextHolder中的用户,该怎么办?(即当前登录的用户)处理originalRunnable?这可以通过从我们的DelegatingSecurityContextExecutor构造函数中删除SecurityContext参数来实现。例如:

  

1 SimpleAsyncTaskExecutor delegateExecutor = new SimpleAsyncTaskExecutor();
2 DelegatingSecurityContextExecutor executor =  new DelegatingSecurityContextExecutor(delegateExecutor);

 

现在,无论何时executor.execute(Runnable)执行,安全上下文SecurityContext 首先由安全上下文持有者SecurityContextHolder 获得,然后该安全上下文SecurityContext用于创建我们的委托安全上下文可运行DelegatingSecurityContextRunnable。这意味着我们用调用执行器的同一个用户执行我们的可运行代码executor.execute(Runnable)。

posted @ 2020-08-15 19:59  节日快乐  阅读(1009)  评论(0编辑  收藏  举报