36.1 DelegatingSecurityContextRunnable委托安全上下文可运行
Spring Security并发支持中最基本的构件之一是delegatingsecuritycontextrunable。它包装一个可运行的委托,以便用为该委托指定的安全上下文SecurityContext 来初始化安全上下文容器SecurityContextHolder 。然后,它调用委托Runnable,确保随后清除SecurityContextHolder。delegatingsecuritycontextrunable看起来像这样:
1 public void run() { 2 try { 3 SecurityContextHolder.setContext(securityContext); 4 delegate.run(); 5 } finally { 6 SecurityContextHolder.clearContext(); 7 } 8 }
虽然非常简单,但它可以无缝地将安全上下文从一个线程转移到另一个线程。这一点很重要,因为在大多数情况下,安全上下文持有者基于每个线程进行操作。例如,您可能使用了Spring Security的第41.4.1节“<global-method-security>”支持来保护您的一项服务。现在,您可以轻松地将当前线程的安全上下文转移到调用安全服务的线程。您可以在下面找到这样做的示例:
1 Runnable originalRunnable = new Runnable() { 2 public void run() { 3 // invoke secured service 4 } 5 }; 6 7 SecurityContext context = SecurityContextHolder.getContext(); 8 DelegatingSecurityContextRunnable wrappedRunnable = new DelegatingSecurityContextRunnable(originalRunnable, context); 10 new Thread(wrappedRunnable).start();
上面的代码执行以下步骤:
创建一个将调用我们的安全服务的Runnable。请注意,它不知道Spring安全性
从SecurityContextHolder获取我们希望使用的安全上下文,并初始化delegatingsecuritycontextrunable
使用delegatingsecuritycontextrunable创建一个线程
启动我们创建的线程
由于从SecurityContextHolder创建一个带有SecurityContext的delegatingsecuritycritycontextranable是很常见的,所以有一个快捷构造函数。以下代码与上面的代码相同:
1 Runnable originalRunnable = new Runnable() { 2 public void run() { 3 // invoke secured service 4 } 5 }; 6 7 DelegatingSecurityContextRunnable wrappedRunnable = new DelegatingSecurityContextRunnable(originalRunnable); 8 new Thread(wrappedRunnable).start();
我们拥有的代码使用起来很简单,但是仍然需要知道我们正在使用Spring Security。在下一节中,我们将了解如何利用delegatingsecuritytycontextexecutor来隐藏我们正在使用Spring Security的事实。