AbstractSecurityInterceptor
可以在安全对象回调期间,暂时替换SecurityContext
和SecurityContextHolder
里的Authentication
对象。
只有在原始Authentication
对象被AuthenticationManager
和AccessDecisionManager
成功处理之后,才有可能发生这种情况。
如果有需要,RunAsManager
会显示替换的Authentication
对象,这应该通过SecurityInterceptorCallback
调用。
通过在安全对象回调过程中临时替换 Authentication
对象,安全调用可以调用其他需要不同认证授权证书的对象。
这也可以为特定的GrantedAuthority
对象执行内部安全检验。
因为Spring Security提供不少帮助类,能够基于SecurityContextHolder
的内容自动配置远程协议,这些运行身份替换在远程web服务调用的时候特别有用。
一个Spring Security提供的 RunAsManager
接口::
Authentication buildRunAs(Authentication authentication, Object object, List<ConfigAttributeDefinition> 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
会通过一个新的GrantedAuthorityImpl
,为每一个RUN_AS_
ConfigAttribute
包含同样的主体,证书,赋予的权限,就像原来的Authentication
对象一样。
每个新 GrantedAuthorityImpl
会以ROLE_
开头,对应RUN_AS
ConfigAttribute
。
比如,一个替代RunAsUserToken
,对于RUN_AS_SERVER
的结果是包含一个ROLE_RUN_AS_SERVER
赋予的权限。
替代的 RunAsUserToken
就像其他 Authentication
对象一样。
它可能需要通过代理合适的AuthenticationProvider
被AuthenticationManager
验证。
这个RunAsImplAuthenticationProvider
执行这样的认证,它直接获得任何一个有效的RunAsUserToken
。
为了保证恶意代码不会创建一个RunAsUserToken
,由RunAsImplAuthenticationProvider
保障获得一个key的散列值被保存在所有生成的标记里。
RunAsManagerImpl
和RunAsImplAuthenticationProvider
在bean上下文里,创建使用同样的key:
<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>
通过使用相同的key,每个RunAsUserToken
可以被它验证,并使用对应的RunAsManagerImpl
创建。
出于安全原因,这个RunAsUserToken
创建后就不能改变。