31

Java 6 / Spring 3に実装されたサービスクラスがあり、ロールごとにアクセスを制限するためのアノテーションが必要です。

値属性としてOperationTypeという列挙型からの1つ以上の値を持つRequiredPermissionというアノテーションを定義しました。

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
   }
}

また、次のアスペクト定義があります。

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

パラメータオブジェクトにはユーザー名が含まれており、メソッドへのアクセスを許可する前に、ユーザーに必要な役割を検索したいと思います。

MyServiceImplのメソッドにアノテーションを付けると、すべてが正常に機能し、ポイントカットが一致し、アスペクトが開始されます。ただし、アノテーションはサービスコントラクトの一部であり、インターフェイスとともに別のAPIパッケージで公開する必要があると思います。 。そして明らかに、サービス定義と実装(DRY)の両方に注釈を付けたくありません。

Spring AOPには、1つのインターフェースメソッド(トランザクションなど)のアノテーションによってアスペクトがトリガーされる場合があることを私は知っています。ここに特別な構文がありますか、それともそのままでは不可能です。

PS:うまく機能しているように見えるので、春の設定を投稿していません。いいえ、それらは私の元のクラス名でもメソッド名でもありません。

PPS:実際、これが私の春の設定の関連部分です:

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

<bean class="com.mycompany.aspect.MyAspect">
    <property name="userService" ref="userService" />
</bean>
4

2 に答える 2

37

私があなたの正しさを理解しているなら、MyServiceを拡張し、注釈が付けられ、優先引数を持つクラス内のすべてのメソッドを見つけるポイントカットが必要です。

私はあなたが置き換えることを提案します:

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

と:

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

プラス記号は、ジョインポイントをMyServiceクラスまたはそれを拡張するクラスと一致させる場合に使用されます。

お役に立てば幸いです。

于 2010-05-17T10:10:53.173 に答える
6

エスペン、あなたのコードは1つのクラスでのみ機能します:

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

しかし、* com.mycompany.services。**パッケージのすべてのサービスでこの動作が必要な場合はどうなりますか?

于 2010-05-18T08:44:54.310 に答える