spring-security/docs/modules/ROOT/pages/servlet/authentication/runas.adoc

66 lines
3.7 KiB
Plaintext

[[runas]]
= Run-As Authentication Replacement
[[runas-overview]]
The `AbstractSecurityInterceptor` is able to temporarily replace the `Authentication` object in the `SecurityContext` and `SecurityContextHolder` during the secure object callback phase.
This only occurs if the original `Authentication` object was successfully processed by the `AuthenticationManager` and `AccessDecisionManager`.
The `RunAsManager` indicates the replacement `Authentication` object, if any, that should be used during the `SecurityInterceptorCallback`.
By temporarily replacing the `Authentication` object during the secure object callback phase, the secured invocation can call other objects that require different authentication and authorization credentials.
It can also perform any internal security checks for specific `GrantedAuthority` objects.
Because Spring Security provides a number of helper classes that automatically configure remoting protocols based on the contents of the `SecurityContextHolder`, these run-as replacements are particularly useful when calling remote web services.
[[runas-config]]
== Configuration
Spring Security provices a `RunAsManager` interface:
====
[source,java]
----
Authentication buildRunAs(Authentication authentication, Object object,
List<ConfigAttribute> config);
boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz);
----
====
The first method returns the `Authentication` object that should replace the existing `Authentication` object for the duration of the method invocation.
If the method returns `null`, it indicates no replacement should be made.
The second method is used by the `AbstractSecurityInterceptor` as part of its startup validation of configuration attributes.
The `supports(Class)` method is called by a security interceptor implementation to ensure that the configured `RunAsManager` supports the type of secure object that the security interceptor presents.
Spring Security provides one concrete implementation of `RunAsManager`.
The `RunAsManagerImpl` class returns a replacement `RunAsUserToken` if any `ConfigAttribute` starts with `RUN_AS_`.
If any such `ConfigAttribute` is found, the replacement `RunAsUserToken` contains the same principal, credentials, and granted authorities as the original `Authentication` object, along with a new `SimpleGrantedAuthority` for each `RUN_AS_` `ConfigAttribute`.
Each new `SimpleGrantedAuthority` is prefixed with `ROLE_`, followed by the `RUN_AS` `ConfigAttribute`.
For example, a `RUN_AS_SERVER` results in the replacement `RunAsUserToken` containing a `ROLE_RUN_AS_SERVER` granted authority.
The replacement `RunAsUserToken` is like any other `Authentication` object.
It needs to be authenticated by the `AuthenticationManager`, probably through delegation to a suitable `AuthenticationProvider`.
The `RunAsImplAuthenticationProvider` performs such authentication.
It accepts as valid any `RunAsUserToken` presented.
To ensure malicious code does not create a `RunAsUserToken` and present it for guaranteed acceptance by the `RunAsImplAuthenticationProvider`, the hash of a key is stored in all generated tokens.
The `RunAsManagerImpl` and `RunAsImplAuthenticationProvider` is created in the bean context with the same key:
====
[source,xml]
----
<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>
----
====
By using the same key, each `RunAsUserToken` can be validated because it was created by an approved `RunAsManagerImpl`.
The `RunAsUserToken` is immutable after creation, for security reasons.