运行中的认证替换

本站(springdoc.cn)中的内容来源于 spring.io ,原始版权归属于 spring.io。由 springdoc.cn 进行翻译,整理。可供个人学习、研究,未经许可,不得进行任何转载、商用或与之相关的行为。 商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。

在 secure 对象回调阶段,AbstractSecurityInterceptor 能够暂时替换 SecurityContextSecurityContextHolder 中的 Authentication 对象。这只发生在原始 Authentication 对象被 AuthenticationManagerAccessDecisionManager 成功处理的情况下。RunAsManager 指出在 SecurityInterceptor 回调期间应该使用的替换 Authentication 对象(如果有的话)。

通过在secure对象回调阶段临时替换 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 支持安全拦截器提出的 secure 对象的类型。

Spring Security 提供了 RunAsManager 的一个具体实现。如果任何 ConfigAttributeRUN_AS_ 开头,RunAsManagerImpl 类会返回一个替换的 RunAsUserToken。如果发现任何这样的 ConfigAttribute,替换的 RunAsUserToken 包含与原始 Authentication 对象相同的委托人(principal)、凭证和授权,以及每个 RUN_AS_ ConfigAttribute 的新 SimpleGrantedAuthority。每个新的 SimpleGrantedAuthority 的前缀是ROLE_,后面是 RUN_AS ConfigAttribute。例如,RUN_AS_SERVER 导致替换的 RunAsUserToken 包含 ROLE_RUN_AS_SERVER 授予的权限。

替换的 RunAsUserToken 和其他的 Authentication 对象一样。它需要被 AuthenticationManager 验证,可能是通过委托给一个合适的 AuthenticationProviderRunAsImplAuthenticationProvider 执行这种认证。它接受任何提交的 RunAsUserToken 为有效。

为了确保恶意代码不会创建 RunAsUserToken 并将其提交给 RunAsImplAuthenticationProvider 保证接受,所有生成的token中都存储了一个密钥的哈希值。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 在创建后是不可改变的。