运行时身份验证替换

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

通过在安全对象回调阶段临时替换 Authentication 对象,安全调用可以调用需要不同身份验证和授权凭据的其他对象。它还可以对特定 GrantedAuthority 对象执行任何内部安全检查。由于 Spring Security 提供了许多帮助程序类,这些类根据 SecurityContextHolder 的内容自动配置远程协议,因此这些运行时替换在调用远程 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 的具体实现。如果任何 ConfigAttributeRUN_AS_ 开头,则 RunAsManagerImpl 类将返回一个替换的 RunAsUserToken。如果找到任何此类 ConfigAttribute,则替换的 RunAsUserToken 将包含与原始 Authentication 对象相同的 principal、凭据和授予的权限,以及每个 RUN_AS_ ConfigAttribute 的新的 SimpleGrantedAuthority。每个新的 SimpleGrantedAuthorityROLE_ 为前缀,后跟 RUN_AS ConfigAttribute。例如,RUN_AS_SERVER 会导致替换的 RunAsUserToken 包含 ROLE_RUN_AS_SERVER 授予的权限。

替换的 RunAsUserToken 与任何其他 Authentication 对象一样。它需要由 AuthenticationManager 进行身份验证,可能是通过委托给合适的 AuthenticationProviderRunAsImplAuthenticationProvider 执行此类身份验证。它接受作为有效的任何呈现的 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 在创建后是不可变的。