2016-05-25 13 views
7

Vorrei utilizzare le annotazioni @PreAuthorize per proteggere i metodi nel controller REST di Spring, utilizzando i parametri del metodo, ad es.Come utilizzare @PathVariable per risolvere il nome del parametro in Spring Security?

@RequestMapping("/something/{myParam}") 
@PreAuthorize("@security.check(#myParam)") 
public String getSomething(@PathVariable("myParam") Integer myParam) { 
    //... 
} 

Spring Security ha bisogno di un modo per scoprire i nomi dei parametri in runtime. Quando non ci sono simboli di debug nella classe compilata, è necessario aggiungere un'annotazione speciale @P o @Param di Spring Data. Così, il metodo sarà simile a questa:

@RequestMapping("/something/{myParam}") 
@PreAuthorize("@security.check(#myParam)") 
public String getSomething(@PathVariable("myParam") @P("myParam) Integer myParam) { 
    //... 
} 

E 'possibile in qualche modo suggerimento Primavera di sicurezza da utilizzare per @PathVariable invece ed evitare annotazioni aggiuntive come @P?

Secondo the documentation, la lettura dei nomi dei parametri dalle annotazioni viene effettuata da AnnotationParameterNameDiscovererche può essere personalizzata per supportare l'attributo valore di qualsiasi annotazione specificata. Tuttavia, non sono riuscito a trovare alcuna informazione su come personalizzare.

BTW, sto usando Java 7 e Spring Security 3.2.9.

+0

quale versione di spring-core usi? –

+0

@RomanSandarkin 4.1.6.RELEASE – pkalinow

+0

grazie. Sembra che abbia trovato una soluzione) –

risposta

1

Dalla documentazione ufficiale di sicurezza della molla GlobalMethodSecurityConfiguration

A volte si potrebbe essere necessario eseguire operazioni che sono più complicate di quelle possibili con l'annotazione annotazione . Per queste istanze, è possibile estendere lo GlobalMethodSecurityConfiguration assicurandosi che l'annotazione @EnableGlobalMethodSecurity sia presente nella sottoclasse. Per esempio, se si voleva fornire una consuetudine MethodSecurityExpressionHandler, è possibile utilizzare il seguente configurazione:

@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { 
    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 
     // ... create and return custom MethodSecurityExpressionHandler ... 
     return expressionHandler; 
    } 
} 

Come nell'esempio di cui sopra è possibile scrivere la vostra abitudine MethodSecurityExpressionHandler o utilizzare il DefaultMethodSecurityExpressionHandler e set vostra abitudine ParameterNameDiscoverer estende il DefaultSecurityParameterNameDiscoverer (o meno)

@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { 
    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 
     DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); 
     expressionHandler.setParameterNameDiscoverer(new CustomParameterNameDiscoverer()); 
     return expressionHandler; 
    } 
} 

Un altro esempio Spring Security Java Config Preview: Custom Method Security

Spero che questo aiuti.

+0

Grazie! Ho usato questa soluzione nella mia configurazione di test - non con uno scopritore di nome parametro personalizzato, ma con 'AnnotationParameterNameDiscoverer', impostando le annotazioni desiderate da usare:' new AnnotationParameterNameDiscoverer (PathVariable.class.getName(), P.class.getName()) '. Funziona. – pkalinow

+0

Sei il benvenuto, lieto di aiutarti. – vzamanillo

2

Dopo la configurazione non è stato testato, ma sulla base di ricerche di sources of spring security, quindi cercate di modificare la configurazione XML Primavera di sicurezza come segue

<security:global-method-security pre-post-annotations="enabled"> 
    <security:expression-handler ref="expressionHandler"/> 
</security:global-method-security> 

<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"> 
    <property name="parameterNameDiscoverer" ref="parameterNameDiscoverer"/> 
</bean> 

<bean id="parameterNameDiscoverer" class="org.springframework.security.core.parameters.AnnotationParameterNameDiscoverer"> 
    <constructor-arg> 
     <list> 
      <value>org.springframework.web.bind.annotation.PathVariable</value> 
     </list> 
    </constructor-arg> 
</bean> 
+0

Grazie! Questa soluzione funziona e l'ho utilizzata nella mia configurazione, con alcune modifiche: 1. Il parametro Costruttore dovrebbe essere un elenco (già modificato la risposta). 2. Questi bean devono essere definiti in mvc-dispatcher-servlet.xml o ovunque siano definiti i controller REST. – pkalinow

4

In breve, è necessario sostituire la creazione di SecurityExpressionHandler nel metodo in modo che impostare il proprio ParameterNameDiscoverer in costume GlobalMethodSecurityConfiguration.

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration { 

    @Autowired 
    private ApplicationContext context; 

    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 
    DefaultMethodSecurityExpressionHandler result = new DefaultMethodSecurityExpressionHandler(); 
    result.setApplicationContext(this.context); 
    result.setParameterNameDiscoverer(new AnnotationParameterNameDiscoverer(PathVariable.class.getName())); 
    return result; 
    } 

} 

Nel sample project si può portare a qualcosa di output della console come questo

2016-06-06 17:09:01.635 INFO 2871 --- [nio-8080-exec-4] c.s.so.q37435824.SecurityService: myParam value from PathVariable equals 1 

migliori saluti

+0

Questa è una soluzione simile alla risposta di vzamanillo, solo senza un parametro ParameterNameDiscoverer personalizzato. In effetti, ho già implementato uno quasi identico. Tuttavia, non imposto applicationContext sul gestore espressioni. È necessario qui? – pkalinow

+0

@pkalinow, sì, è necessario impostare applicationContext, altrimenti si otterrà il 'No bean resolver registrato nel contesto per risolvere l'accesso a bean 'securityService'' SpelEvaluationException durante la valutazione dell'espressione SpEL –

+0

Non riesco ad ottenere un tale errore. Forse perché uso anche un'altra classe '@ Configuration' per la sicurezza web - estendendo' WebSecurityConfigurerAdapter'? – pkalinow

0

da Official sicurezza Primavera vedere documentation il caso d'uso richiesto può essere raggiunto. Ma per usare devi aggiornare alla versione 4.1.0, non l'ho provato da un aspetto come questo è realizzabile

+0

Sapevo di questo metodo, ma non era esattamente quello di cui avevo bisogno. Voglio usare annotazioni di metodo sui controller, non sui pattern URI. – pkalinow

Problemi correlati