Run-As Authentication Replacement

AbstractSecurityInterceptor 能够在安全对象回调阶段临时替换 SecurityContextSecurityContextHolder 中的 Authentication 对象。此情况仅发生在原始 Authentication 对象已由 AuthenticationManagerAccessDecisionManager 成功处理的情况下。RunAsManager 指示应在 SecurityInterceptorCallback 期间使用的替换 Authentication 对象(如果存在)。

The AbstractSecurityInterceptor is able to temporarily replace the Authentication object in the SecurityContext and SecurityContextHolder during the secure object callback phase. This only occurs if the original Authentication object was successfully processed by the AuthenticationManager and AccessDecisionManager. The RunAsManager indicates the replacement Authentication object, if any, that should be used during the SecurityInterceptorCallback.

通过在安全对象回调阶段临时替换 Authentication 对象,安全调用可以调用需要其他身份验证和授权凭证的其他对象。它还可以对特定 GrantedAuthority 对象执行任何内部安全检查。由于 Spring Security 提供了许多帮助类,这些帮助类可以根据 SecurityContextHolder 的内容自动配置远程协议,因此在调用远程 Web 服务时,这些替代特别有用。

By temporarily replacing the Authentication object during the secure object callback phase, the secured invocation can call other objects that require different authentication and authorization credentials. It can also perform any internal security checks for specific GrantedAuthority objects. Because Spring Security provides a number of helper classes that automatically configure remoting protocols based on the contents of the SecurityContextHolder, these run-as replacements are particularly useful when calling remote web services.

Configuration

Spring Security 提供了 RunAsManager 接口:

Spring Security provices a RunAsManager interface:

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

boolean supports(ConfigAttribute attribute);

boolean supports(Class clazz);

第一个方法返回 Authentication 对象,该对象应在方法调用期间替换现有的 Authentication 对象。如果方法返回 null,则表示不应进行替换。第二个方法由 AbstractSecurityInterceptor 用于对其配置属性进行启动验证。supports(Class) 方法由安全拦截器实现调用,以确保已配置的 RunAsManager 支持安全拦截器呈现的安全对象类型。

The first method returns the Authentication object that should replace the existing Authentication object for the duration of the method invocation. If the method returns null, it indicates no replacement should be made. The second method is used by the AbstractSecurityInterceptor as part of its startup validation of configuration attributes. The supports(Class) method is called by a security interceptor implementation to ensure that the configured RunAsManager supports the type of secure object that the security interceptor presents.

Spring Security 为 RunAsManager 提供了一个具体的实现。RunAsManagerImpl 类返回一个替换 RunAsUserToken(如果任何 ConfigAttributeRUN_AS_ 开头)。如果找到这样的 ConfigAttribute,则替换 RunAsUserToken 包含与原始 Authentication 对象相同的负责人、凭证和授权,并为每个 RUN_AS_ ConfigAttribute 添加一个新 SimpleGrantedAuthority。每个新 SimpleGrantedAuthority 都以 ROLE_ 为前缀,后跟 RUN_AS ConfigAttribute。例如,RUN_AS_SERVER 导致替换 RunAsUserToken 包含 ROLE_RUN_AS_SERVER 授权。

Spring Security provides one concrete implementation of RunAsManager. The RunAsManagerImpl class returns a replacement RunAsUserToken if any ConfigAttribute starts with RUN_AS_. If any such ConfigAttribute is found, the replacement RunAsUserToken contains the same principal, credentials, and granted authorities as the original Authentication object, along with a new SimpleGrantedAuthority for each RUN_AS_ ConfigAttribute. Each new SimpleGrantedAuthority is prefixed with ROLE_, followed by the RUN_AS ConfigAttribute. For example, a RUN_AS_SERVER results in the replacement RunAsUserToken containing a ROLE_RUN_AS_SERVER granted authority.

替换 RunAsUserToken 就像任何其他 Authentication 对象。它需要由 AuthenticationManager(可能通过委派给合适的 AuthenticationProvider)进行验证。RunAsImplAuthenticationProvider 执行此类身份验证。它接受任何介绍的 RunAsUserToken 为有效。

The replacement RunAsUserToken is like any other Authentication object. It needs to be authenticated by the AuthenticationManager, probably through delegation to a suitable AuthenticationProvider. The RunAsImplAuthenticationProvider performs such authentication. It accepts as valid any RunAsUserToken presented.

为了确保恶意代码不会创建 RunAsUserToken 并且向 RunAsImplAuthenticationProvider 展示以保证接受,密钥的哈希存储在所有生成的令牌中。RunAsManagerImplRunAsImplAuthenticationProvider 在 Bean 上下文中使用相同的密钥创建:

To ensure malicious code does not create a RunAsUserToken and present it for guaranteed acceptance by the RunAsImplAuthenticationProvider, the hash of a key is stored in all generated tokens. The RunAsManagerImpl and RunAsImplAuthenticationProvider is created in the bean context with the same key:

<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 在创建后不可变。

By using the same key, each RunAsUserToken can be validated because it was created by an approved RunAsManagerImpl. The RunAsUserToken is immutable after creation, for security reasons.