上周我宣布了 Spring Security 3.2 M1 的发布,其中包含了改进的 Servlet 3 支持。在这篇帖子中,我将介绍 3.2 M1 版本中一些更精彩的功能。具体来说,我们将看看以下 Spring Security 新功能:
并发支持
您可能会问:“为什么在这个以 Servlet 3 为主题的版本中会有并发支持?”原因是并发支持为该版本中的所有其他功能提供了基础。虽然并发支持被 Servlet 3 集成所使用,但它也可以作为构建块,在任何应用程序中支持并发和 Spring Security。现在让我们来看看 Spring Security 的并发支持。
DelegatingSecurityContextRunnable
Spring Security 并发支持中最基本的构建块之一是 `DelegatingSecurityContextRunnable`。它包装了一个委托的 `Runnable`,以便使用指定的 `SecurityContext` 来初始化 `SecurityContextHolder`。然后,它调用委托的 `Runnable`,并确保之后清除 `SecurityContextHolder`。`DelegatingSecurityContextRunnable` 看起来如下:
public void run() {
try {
SecurityContextHolder.setContext(securityContext);
delegate.run();
} finally {
SecurityContextHolder.clearContext();
}
}
虽然很简单,但它能够无缝地将 `SecurityContext` 从一个 `Thread` 转移到另一个 `Thread`。这很重要,因为在大多数情况下,`SecurityContextHolder` 是基于每个 `Thread` 进行操作的。例如,您可能已经使用了 Spring Security 的 <global-method-security> 支持来保护您的某个服务。现在,您可以轻松地将当前 `Thread` 的 `SecurityContext` 转移到调用受保护服务的 `Thread`。下面的示例展示了如何做到这一点:
Runnable originalRunnable = new Runnable() {
public void run() {
// invoke secured service
}
};
SecurityContext context = SecurityContextHolder.getContext();
DelegatingSecurityContextRunnable wrappedRunnable =
new DelegatingSecurityContextRunnable(originalRunnable, context);
new Thread(wrappedRunnable).start();
上面的代码执行以下步骤:
- 创建一个将调用我们受保护服务的 `Runnable`。请注意,它不知道 Spring Security。
- 从 `SecurityContextHolder` 获取我们想要使用的 `SecurityContext`,并初始化 `DelegatingSecurityContextRunnable`。
- 使用 `DelegatingSecurityContextRunnable` 来创建一个 `Thread`。
- 启动我们创建的 `Thread`。
由于使用 `SecurityContextHolder` 中的 `SecurityContext` 来创建 `DelegatingSecurityContextRunnable` 非常常见,因此提供了一个快捷构造函数。以下代码与上面的代码相同:
Runnable originalRunnable = new Runnable() {
public void run() {
// invoke secured…