Domanda

Ho una classe di servizio implementata in Java 6/Spring 3 che necessita di un'annotazione per limitare l'accesso in base al ruolo.

Ho definito un'annotazione chiamata RequiredPermission che ha come attributo valore uno o più valori da un'enumerazione chiamata OperationType:

public @interface RequiredPermission {

/**
 * One or more {@link OperationType}s that map to the permissions required
 * to execute this method.
 * 
 * @return
 */
OperationType[] value();}

public enum OperationType {
      TYPE1,
      TYPE2;
}

package com.mycompany.myservice;
public interface MyService{
   @RequiredPermission(OperationType.TYPE1)
   void myMethod( MyParameterObject obj );
}

package com.mycompany.myserviceimpl;
public class MyServiceImpl implements MyService{
   public myMethod( MyParameterObject obj ){
       // do stuff here
   }
}

Ho anche la seguente definizione di aspetto:

/**
 * Security advice around methods that are annotated with
 * {@link RequiredPermission}.
 * 
 * @param pjp
 * @param param
 * @param requiredPermission
 * @return
 * @throws Throwable
 */
@Around(value = "execution(public *"
        + " com.mycompany.myserviceimpl.*(..))"
        + " && args(param)" + // parameter object
        " && @annotation( requiredPermission )" // permission annotation

, argNames = "param,requiredPermission")
public Object processRequest(final ProceedingJoinPoint pjp,
        final MyParameterObject param,
        final RequiredPermission requiredPermission) throws Throwable {
    if(userService.userHasRoles(param.getUsername(),requiredPermission.values()){
        return pjp.proceed();
    }else{
        throw new SorryButYouAreNotAllowedToDoThatException(
            param.getUsername(),requiredPermission.value());
    }
}

L'oggetto parametro contiene un nome utente e desidero cercare il ruolo richiesto per l'utente prima di consentire l'accesso al metodo.

Quando inserisco l'annotazione sul metodo in MyServiceImpl, tutto funziona perfettamente, il punto di taglio viene abbinato e l'aspetto entra in gioco.Tuttavia, ritengo che l'annotazione faccia parte del contratto di servizio e dovrebbe essere pubblicata con l'interfaccia in un pacchetto API separato.E ovviamente non vorrei inserire l'annotazione sia sulla definizione che sull'implementazione del servizio (DRY).

So che ci sono casi in Spring AOP in cui gli aspetti vengono attivati ​​dalle annotazioni su metodi di interfaccia (ad es.Transazionale).C'è una sintassi speciale qui o è semplicemente impossibile fuori dagli schemi.

PS:Non ho pubblicato la mia configurazione primaverile, poiché sembra che funzioni perfettamente.E no, quelli non sono né la mia classe originale né i nomi dei metodi.

PP:In realtà, ecco la parte rilevante della mia configurazione primaverile:

<aop:aspectj-autoproxy proxy-target-class="false" />

<bean class="com.mycompany.aspect.MyAspect">
    <property name="userService" ref="userService" />
</bean>
È stato utile?

Soluzione

Se ho capito bene, vuoi un punto che trovi tutti i metodi nelle classi che estendono MyService e che sia annotato e con gli argomenti preferiti.

Propongo di sostituire:

execution(public * com.mycompany.myserviceimpl.*(..))

con:

execution(public * com.mycompany.myservice.MyService+.*(..))

Il segno più viene utilizzato se si desidera che un punto di unione corrisponda alla classe MyService o a una classe che la estende.

Spero possa essere d'aiuto!

Altri suggerimenti

Espen, il tuo codice funziona solo per una classe:

execution(public * com.mycompany.myservice.MyService+.*(..))

ma cosa succede se desidero questo comportamento per tutti i servizi nel pacchetto *com.mycompany.services.**?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top