2010-04-01 10 views
13

Vorrei implementare la sicurezza dichiarativa con Spring/AOP e le annotazioni. Come si vede nel prossimo esempio di codice, ho le Annotazioni Restricted con il parametro "allowedRoles" per definire chi è autorizzato ad eseguire un metodo consigliato.Spring AOP: come ottenere le annotazioni del metodo consigliato

@Restricted(allowedRoles="jira-administrators") 
     public void setPassword(...) throws UserMgmtException {    
       // set password code 
       ... 
     } 

Ora, il problema è che nel mio Consigli non ho accesso alle annotazioni definite:

public Object checkPermission(ProceedingJoinPoint pjp) throws Throwable { 

    Signature signature = pjp.getSignature(); 
    System.out.println("Allowed:" + rolesAllowedForJoinPoint(pjp)); 
      ... 
} 

private Restricted rolesAllowedForJoinPoint(ProceedingJoinPoint thisJoinPoint) 
     { 
      MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature(); 
      Method targetMethod = methodSignature.getMethod(); 

      return targetMethod.getAnnotation(Restricted.class); 
     } 

Il metodo di cui sopra restituisce sempre null (non ci sono annotazioni trovati a tutti). C'è una soluzione semplice a questo?

Ho letto qualcosa sull'utilizzo dell'agente AspectJ ma preferirei non utilizzare questo agente.

risposta

13

Presumo @Restricted è la tua annotazione. In questo caso, assicurati di avere:

@Retention(RetentionPolicy.RUNTIME) 

nella definizione di annotazione. Ciò significa che l'annotazione viene mantenuta in fase di runtime.

+0

Grazie mille, che era la ragione. – hugri

2

Perché non usi solo lo Spring Security? È breve da implementare e utilizzare, non vedo davvero il punto nel perdere tempo a reinventare la ruota.

+0

Grazie, lo vedrò presto – hugri

4

Anche dopo aver cambiato il criterio di conservazione come Bozho menzionato questa chiamata per ottenere rendimenti di annotazione NULL:

targetMethod.getAnnotation(Restricted.class); 

Quello che ho trovato è che devi legare l'annotazione. Data l'interfaccia è dichiarata in questo modo:

@Retention(RetentionPolicy.RUNTIME) 
public @interface Restricted { 
    String[] allowedRoles(); 
    } 

Il consiglio avrebbe bisogno di essere dichiarati in questo modo:

 @Before("@annotation(restrictedAnnotation)") 
     public Object processRequest(final ProceedingJoinPoint pjp, Restricted restrictedAnnotation) throws Throwable { 
        String[] roles = restrictedAnnotation.allowedRoles(); 
        System.out.println("Allowed:" + roles); 
     } 

Quello che fa è legano l'annotazione al parametro nella firma del metodo, restrictedAnnotation. La parte di cui non sono sicuro è come ottiene il tipo di annotazione, sembra essere basato sul parametro. E una volta che hai l'annotazione puoi ottenere i valori.

2

Whith Spring AOP se si dispone di una situazione come MyManagerImpl implements MyManager il pointcut viene applicato al metodo interface modo MethodSignature descrive il metodo definito in MyManager che non ha alcuna annotazione. l'unico modo per risolvere questo problema è ispezionare la classe dell'oggetto jp.getTarget() e recuperare il metodo corrispondente.

27

A chi ha ancora il problema dopo il modifica della conservazione delle annotazioni in Runtime, si potrebbe avere lo stesso problema che avevo: getMethod() restituisce il metodo di interfaccia invece della classe di implementazione. Quindi, se hai le annotazioni nella classe, naturalmente getAnnotations() sul metodo dell'interfaccia restituisce null.

La seguente soluzione risolto questo problema:

final String methodName = pjp.getSignature().getName(); 
final MethodSignature methodSignature = (MethodSignature)pjp.getSignature(); 
Method method = methodSignature.getMethod(); 
if (method.getDeclaringClass().isInterface()) { 
    method = pjp.getTarget().getClass().getDeclaredMethod(methodName, method.getParameterTypes());  
} 

e se ti piace, si ha la possibilità di gestire le annotazioni di interfaccia anche qui.

Alcuni altri commenti disponibili qui: getting template method instance from ProceedingJoinPoint

Oleg

+0

Ciao, grazie mille del futuro! –