ho raggiunto che mediante l'attuazione di mia AccessDecisionManager
che i delegati l'accesso decisioni al mio speciale interfaccia AccessDecisionStrategy
: strategia decisione
public interface AccessDecisionStrategy {
void decide(Authentication authentication, MethodInvocation methodInvocation, ConfigAttribute configAttribute);
}
Ogni accesso rappresenta modo diverso di fare decisione accesso.
Si può facilmente implementare la propria strategia (anche in altra lingua - per esempio Scala):
public class SomeStrategy implements AccessDecisionStrategy { ...
Come si può vedere, il mio AccessDecisionManager
ha una mappa delle strategie. La strategia utilizzata dal gestore si basa sull'argomento di annotazione.
public class MethodSecurityAccessDecisionManager implements AccessDecisionManager {
private Map<String, AccessDecisionStrategy> strategyMap;
public MethodSecurityAccessDecisionManager(Map<String, AccessDecisionStrategy> strategyMap) {
this.strategyMap = strategyMap;
}
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
ConfigAttribute configAttribute = getSingleConfigAttribute(configAttributes);
AccessDecisionStrategy accessDecisionStrategy = strategyMap.get(configAttribute.getAttribute());
if (accessDecisionStrategy == null) {
throw new IllegalStateException("AccessDecisionStrategy with name "
+ configAttribute.getAttribute() + " was not found!");
}
try {
accessDecisionStrategy.decide(authentication, (MethodInvocation) object, configAttribute);
} catch (ClassCastException e) {
throw new IllegalStateException();
}
}
private ConfigAttribute getSingleConfigAttribute(Collection<ConfigAttribute> configAttributes) {
if (configAttributes == null || configAttributes.size() != 1) {
throw new IllegalStateException("Invalid config attribute configuration");
}
return configAttributes.iterator().next();
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return clazz.equals(MethodInvocation.class);
}
}
Ora, quando voglio proteggere il mio metodo ho messo @Secured
annotazione con argomento che è il nome della strategia:
@Secured("GetByOwner")
FlightSpotting getFlightSpotting(Long id);
È possibile implementare e configurare come molte strategie che vuoi:
Per inserire il gestore delle decisioni di accesso digitare:
<sec:global-method-security secured-annotations="enabled"
access-decision-manager-ref="methodSecurityAccessDecisionManager">
</sec:global-method-security>
ho classe di supporto anche implementato per gestire MethodInvocation
argomenti:
import org.aopalliance.intercept.MethodInvocation;
public class MethodInvocationExtractor<ArgumentType> {
private MethodInvocation methodInvocation;
public MethodInvocationExtractor(MethodInvocation methodInvocation) {
this.methodInvocation = methodInvocation;
}
public ArgumentType getArg(int num) {
try {
Object[] arguments = methodInvocation.getArguments();
return (ArgumentType) arguments[num];
} catch (ClassCastException | ArrayIndexOutOfBoundsException e) {
throw new IllegalStateException();
}
}
}
Ora si può facilmente estrarre argomenti interessanti nel codice della vostra strategia di prendere decisioni:
Diciamo che voglio ottenere il numero argomento 0
che è di tipo Long
:
MethodInvocationExtractor<Long> extractor = new MethodInvocationExtractor<>(methodInvocation);
Long id = extractor.getArg(0);
+1 per il puntatore per lanciare oggetti per MethodInvocation a decidere(). I documenti di Spring mancano di quella parte vitale di informazioni ... –
Nel caso qualcuno ne abbia bisogno, ho aggiunto come implementarlo usando Java Config (il mio progetto usa Spring-Boot) [in questa nuova domanda] (http: // stackoverflow. com/q/24983046/2.796.922). Vedi la mia risposta. – elysch
Per molti casi d'uso non è necessario implementare il proprio decision manager. Invece puoi semplicemente scrivere un metodo e chiamarlo direttamente da '@ Preauthorize', vedi questa risposta: http://stackoverflow.com/a/39972346/1169324 –