Question

J'ai une classe de service en Java 6 / Spring 3 qui a besoin d'une annotation pour restreindre l'accès par rôle.

I ai défini une annotation appelée RequiredPermission qui a pour une valeur d'attribut d'une ou plusieurs valeurs d'un enum appelé 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
   }
}

J'ai aussi la définition d'aspect suivant:

/**
 * 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'objet de paramètre contient un nom d'utilisateur et je veux regarder le rôle nécessaire à l'utilisateur avant d'autoriser l'accès à la méthode.

Quand je mets l'annotation sur la méthode MyServiceImpl, tout fonctionne très bien, pointcut est adaptée et l'aspect est. Cependant, je crois que l'annotation fait partie du contrat de service et devrait être publié avec l'interface dans un package API séparée. Et évidemment, je ne voudrais pas mettre l'annotation à la fois sur la définition du service et la mise en œuvre (SEC).

Je sais qu'il ya des cas dans Spring AOP où les aspects sont déclenchés par des annotations une des méthodes d'interface (par exemple transactionnelles). Y at-il une syntaxe spéciale ici ou est-il tout simplement impossible de la boîte.

PS: Je n'ai pas posté ma config de printemps, comme il semble fonctionner très bien. Et non, ceux qui ne sont ni ma classe d'origine, ni les noms méthode.

PPS: En fait, voici la partie pertinente de ma config de printemps:

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

<bean class="com.mycompany.aspect.MyAspect">
    <property name="userService" ref="userService" />
</bean>
Était-ce utile?

La solution

Si je vous comprends correct, vous voulez un pointcut qui trouve toutes les méthodes dans les classes qui MyService et est étend annotés et avec les arguments préférés.

Je vous propose de remplacer:

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

avec:

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

Le signe plus est utilisé si vous voulez un point de jonction pour correspondre à la classe MyService ou une classe qui la prolonge.

J'espère que ça aide!

Autres conseils

Espen, votre code ne fonctionne que pour une classe:

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

mais si je veux que ce comportement pour tous les services * com.mycompany.services. Package **?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top