Run-As Authentication Replacement

AbstractSecurityInterceptor 能够在安全对象回调阶段临时替换 SecurityContextSecurityContextHolder 中的 Authentication 对象。此情况仅发生在原始 Authentication 对象已由 AuthenticationManagerAccessDecisionManager 成功处理的情况下。RunAsManager 指示应在 SecurityInterceptorCallback 期间使用的替换 Authentication 对象(如果存在)。 通过在安全对象回调阶段临时替换 Authentication 对象,安全调用可以调用需要其他身份验证和授权凭证的其他对象。它还可以对特定 GrantedAuthority 对象执行任何内部安全检查。由于 Spring Security 提供了许多帮助类,这些帮助类可以根据 SecurityContextHolder 的内容自动配置远程协议,因此在调用远程 Web 服务时,这些替代特别有用。

Configuration

Spring Security 提供了 RunAsManager 接口:

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

boolean supports(ConfigAttribute attribute);

boolean supports(Class clazz);

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

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 授权。

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

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

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