# run-as 身份验证替换

# 概述

在安全对象回调阶段,AbstractSecurityInterceptor可以在SecurityContextSecurityContextHolder中临时替换Authentication对象。只有当原始Authentication对象被AuthenticationManagerAccessDecisionManager成功处理时,才会发生这种情况。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,如果有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进行身份验证,很可能是通过将其委托给合适的AuthenticationProviderRunAsImplAuthenticationProvider执行这种身份验证。它只是接受任何RunAsUserToken呈现为有效。

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

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

X509Logout