|
此版本仍在开发中,尚未被视为稳定版本。如需最新稳定版本,请使用 Spring Security 7.0.4! |
Run-As 身份验证替换
AbstractSecurityInterceptor 能够在安全对象回调阶段临时替换 Authentication 对象中的 SecurityContext 和 SecurityContextHolder。
仅当原始 Authentication 对象被 AuthenticationManager 和 AccessDecisionManager 成功处理时,才会发生这种情况。
RunAsManager 指示在 SecurityInterceptorCallback 期间应使用的替代 Authentication 对象(如果有的话)。
通过在安全对象回调阶段临时替换Authentication对象,被保护的调用可以调用其他需要不同身份验证和授权凭据的对象。
它还可以针对特定的GrantedAuthority对象执行任何内部安全检查。
由于Spring Security提供了多个辅助类,这些类会根据SecurityContextHolder的内容自动配置远程通信协议,因此这种“以...身份运行”(run-as)替换在调用远程Web服务时特别有用。
配置
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 类会在任何 ConfigAttribute 以 RUN_AS_ 开头时返回一个替换的 RunAsUserToken。
如果找到任何这样的 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 作为有效Tokens。
为防止恶意代码创建一个 RunAsUserToken 并将其提交给 RunAsImplAuthenticationProvider 以确保被无条件接受,所有生成的Tokens中都会存储一个密钥的哈希值。
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 在创建后是不可变的。