Pergunta

Eu tenho uma classe de serviço implementada no Java 6 / Spring 3 que precisa de uma anotação para restringir o acesso por função.

Defini uma anotação chamada requeririssão que tenha como atributo de valor um ou mais valores de um enum chamado 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
   }
}

Eu também tenho a seguinte definição de aspecto:

/**
 * 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());
    }
}

O objeto do parâmetro contém um nome de usuário e quero procurar a função necessária para o usuário antes de permitir o acesso ao método.

Quando coloquei a anotação no método em MyServiceImpl, tudo funciona bem, o Pointcut é comparado e o aspecto entra em ação. No entanto, acredito que a anotação faz parte do contrato de serviço e deve ser publicada com a interface em um pacote de API separado . E, obviamente, eu não gostaria de colocar a anotação na definição e na implementação do serviço (seca).

Sei que há casos na Spring AOP onde os aspectos são acionados por métodos de interface anotações um (por exemplo, transacionais). Existe uma sintaxe especial aqui ou é simplesmente impossível pronta para fora da caixa.

PS: Eu não publiquei minha configuração de primavera, pois parece estar funcionando muito bem. E não, esses não são os nomes da minha classe original nem de métodos.

PPS: Na verdade, aqui está a parte relevante da minha configuração da primavera:

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

<bean class="com.mycompany.aspect.MyAspect">
    <property name="userService" ref="userService" />
</bean>
Foi útil?

Solução

Se eu entendo que você corrija, você deseja um ponto de ponta que encontra todos os métodos nas classes que estendem o MyService e são anotados e com os argumentos preferidos.

Eu proponho que você substitua:

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

com:

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

O sinal de plus é usado se você deseja um ponto de junção para corresponder à classe MyService ou a uma classe que a estende.

Espero que ajude!

Outras dicas

Espen, seu código funciona apenas para uma classe:

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

Mas e se eu quiser esse comportamento para todos os serviços no pacote*com.mycompany.services. **?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top