# run-as 身份验证替换

## 概述

在安全对象回调阶段，`AbstractSecurityInterceptor`可以在`SecurityContext`和`SecurityContextHolder`中临时替换`Authentication`对象。只有当原始`Authentication`对象被`AuthenticationManager`和`AccessDecisionManager`成功处理时，才会发生这种情况。`RunAsManager`将指示在`SecurityInterceptorCallback`期间应该使用的替换`Authentication`对象（如果有的话）。

通过在安全对象回调阶段临时替换`Authentication`对象，安全调用将能够调用需要不同身份验证和授权凭据的其他对象。它还能够对特定的`GrantedAuthority`对象执行任何内部安全检查。因为 Spring Security 提供了许多帮助器类，这些帮助器类根据`SecurityContextHolder`的内容自动配置远程协议，所以在调用远程 Web 服务时，这些 run-as 替换特别有用。

## 配置

一个`RunAsManager`接口由 Spring Security 提供：

```
Authentication buildRunAs(Authentication authentication, Object object,
	List<ConfigAttribute> config);

boolean supports(ConfigAttribute attribute);

boolean supports(Class clazz);
```

第一个方法返回`Authentication`对象，该对象应该在方法调用的持续时间内替换现有的`Authentication`对象。如果该方法返回`null`，则表示不应进行替换。第二种方法由`AbstractSecurityInterceptor`使用，作为其配置属性的启动验证的一部分。安全拦截器实现调用`supports(Class)`方法，以确保配置的`RunAsManager`支持安全拦截器将呈现的安全对象类型。

一个`RunAsManager`的具体实现提供了 Spring 安全性。`RunAsManagerImpl`类返回一个替换`RunAsUserToken`，如果有`ConfigAttribute`以`RUN_AS_`开头。如果找到任何这样的`ConfigAttribute`，则替换的`RunAsUserToken`将包含与原始`Authentication`对象相同的主体、凭据和授予的权限，以及每个`RUN_AS_``ConfigAttribute`的新`SimpleGrantedAuthority`。每个新的`SimpleGrantedAuthority`都将被前缀为`ROLE_`，然后是`RUN_AS``ConfigAttribute`。例如，一个`RUN_AS_SERVER`将导致替换`RunAsUserToken`中包含一个`ROLE_RUN_AS_SERVER`授予的权限。

替换`RunAsUserToken`就像任何其他`Authentication`对象一样。它需要通过`AuthenticationManager`进行身份验证，很可能是通过将其委托给合适的`AuthenticationProvider`。`RunAsImplAuthenticationProvider`执行这种身份验证。它只是接受任何`RunAsUserToken`呈现为有效。

为了确保恶意代码不会创建`RunAsUserToken`，并将其呈现给`RunAsImplAuthenticationProvider`，密钥的散列存储在所有生成的令牌中。在 Bean 上下文中使用相同的键创建`RunAsManagerImpl`和`RunAsImplAuthenticationProvider`:

```
<bean id="runAsManager"
	class="org.springframework.security.access.intercept.RunAsManagerImpl">
<property name="key" value="my_run_as_password"/>
</bean>

<bean id="runAsAuthenticationProvider"
	class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">
<property name="key" value="my_run_as_password"/>
</bean>
```

通过使用相同的键，每个`RunAsUserToken`都可以验证它是由批准的`RunAsManagerImpl`创建的。出于安全原因，`RunAsUserToken`在创建后是不可变的

[X509](x509.html)[Logout](logout.html)

