Ich habe a detailed article auf die Implementierung von Run-As in Verbindung mit @PreAuthorize
veröffentlicht.
1) Implementieren Sie Ihre eigene RunAsManager
, die die Authentication
erstellt, um während der Methodenausführung basierend auf beliebiger benutzerdefinierter Logik zu verwenden. Das folgende Beispiel verwendet eine benutzerdefinierte Anmerkung, die die zusätzliche Rolle bietet:
public class AnnotationDrivenRunAsManager extends RunAsManagerImpl {
@Override
public Authentication buildRunAs(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
if(!(object instanceof ReflectiveMethodInvocation) || ((ReflectiveMethodInvocation)object).getMethod().getAnnotation(RunAsRole.class) == null) {
return super.buildRunAs(authentication, object, attributes);
}
String roleName = ((ReflectiveMethodInvocation)object).getMethod().getAnnotation(RunAsRole.class).value();
if (roleName == null || roleName.isEmpty()) {
return null;
}
GrantedAuthority runAsAuthority = new SimpleGrantedAuthority(roleName);
List<GrantedAuthority> newAuthorities = new ArrayList<GrantedAuthority>();
// Add existing authorities
newAuthorities.addAll(authentication.getAuthorities());
// Add the new run-as authority
newAuthorities.add(runAsAuthority);
return new RunAsUserToken(getKey(), authentication.getPrincipal(), authentication.getCredentials(),
newAuthorities, authentication.getClass());
}
}
Diese Implementierung für eine benutzerdefinierte @RunAsRole
Anmerkung auf einem geschützten Verfahren aussehen wird (zB @RunAsRole("ROLE_AUDITOR")
) und, falls gefunden wird, wird die gegebene Autorität hinzufügen (ROLE_AUDITOR
in diesem Fall) in die Liste der erteilten Behörden aufgenommen. RunAsRole
selbst ist nur eine einfache benutzerdefinierte Anmerkung.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RunAsRole {
String value();
}
2) Instantiate den Manager:
<bean id="runAsManager"
class="org.springframework.security.access.intercept.RunAsManagerImpl">
<property name="key" value="my_run_as_key"/>
</bean>
3) Registrieren Sie:
<global-method-security pre-post-annotations="enabled" run-as-manager-ref="runAsManager">
<expression-handler ref="expressionHandler"/>
</global-method-security>
4) Beispiel für die Verwendung in einem Controller:
@Controller
public class TransactionLogController {
@PreAuthorize("hasRole('ROLE_REGISTERED_USER')") //Authority needed to access the method
@RunAsRole("ROLE_AUDITOR") //Authority added by RunAsManager
@RequestMapping(value = "/transactions", method = RequestMethod.GET) //Spring MVC configuration. Not related to security
@ResponseBody //Spring MVC configuration. Not related to security
public List<Transaction> getTransactionLog(...) {
... //Invoke something in the backend requiring ROLE_AUDITOR
{
... //User does not have ROLE_AUDITOR here
}
EDIT: Der Wert von key
in RunAsManagerImpl
kann alles sein, was Sie wollen. Hier ist der Auszug aus Spring docs auf seine Verwendung:
, um bösartigen Code sicherzustellen, keine RunAsUserToken
und Gegenwart es für garantierte Akzeptanz schaffen durch die RunAsImplAuthenticationProvider
, den Hash eines Schlüssels wird in allen generierten Token gespeichert. Die RunAsManagerImpl
und RunAsImplAuthenticationProvider
ist in der bean Zusammenhang mit dem gleichen Schlüssel erstellt:
<bean id="runAsManager"
class="org.springframework.security.access.intercept.RunAsManagerImpl">
<bean id="runAsAuthenticationProvider"
class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">
Durch die Verwendung des gleichen Schlüssel, jeder RunAsUserToken
validiert werden kann es erstellt wurde von einem genehmigt RunAsManagerImpl
.Die RunAsUserToken
ist aus Sicherheitsgründen nach unveränderbar.
Wofür wird "my_run_as_key" verwendet? - Ich kann das nicht herausfinden. Ich habe wahrscheinlich den gleichen Leitfaden gelesen, den Sie hier zitiert haben, aber dieser Schlüssel ergibt für mich keinen Sinn. –
@DanielBo Der Wert kann alles sein, was Sie wollen. Es ist im Grunde ein Passwort. Ich habe die Antwort aktualisiert, um Spring docs zu zitieren, warum es benötigt wird. – kaqqao