34. 运行身份验证替换
34.1 Overview
AbstractSecurityInterceptor
可以在安全对象回调阶段临时替换SecurityContext
和SecurityContextHolder
中的Authentication
对象。仅当AuthenticationManager
和AccessDecisionManager
成功处理了原始Authentication
对象时,才会发生这种情况。 RunAsManager
将指示在SecurityInterceptorCallback
期间应使用的替换Authentication
对象(如果有)。
通过在安全对象回调阶段临时替换Authentication
对象,安全调用将能够调用需要不同身份验证和授权凭证的其他对象。它还将能够对特定的GrantedAuthority
对象执行任何内部安全检查。因为 Spring Security 提供了许多帮助程序类,它们基于SecurityContextHolder
的内容自动配置远程协议,所以这些运行方式替换在调用远程 Web 服务时特别有用。
34.2 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
的一种具体实现。如果ConfigAttribute
以RUN_AS_
开头,则RunAsManagerImpl
类返回替换RunAsUserToken
。如果找到任何这样的ConfigAttribute
,则替换RunAsUserToken
将包含与原始Authentication
对象相同的主体,凭据和授予的权限,以及每个RUN_AS_
ConfigAttribute
的新SimpleGrantedAuthority
。每个新的SimpleGrantedAuthority
都将带有ROLE_
前缀,然后是RUN_AS
ConfigAttribute
。例如,RUN_AS_SERVER
将导致包含ROLE_RUN_AS_SERVER
授予的权限的替换RunAsUserToken
。
替换RunAsUserToken
就像其他任何Authentication
对象一样。它需要由AuthenticationManager
进行身份验证,可能需要通过委派给合适的AuthenticationProvider
来进行。 RunAsImplAuthenticationProvider
执行这种认证。它只是接受任何出现的RunAsUserToken
作为有效值。
为了确保恶意代码不会创建RunAsUserToken
并将其呈现出来以确保被RunAsImplAuthenticationProvider
接受,密钥的哈希存储在所有生成的令牌中。 RunAsManagerImpl
和RunAsImplAuthenticationProvider
是在 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
是不可变的