2012-02-16 12 views
2

私は、ログインによってほぼ完全に保護されるWebサイトを作成しています(Spring Securityを使用しています)。 (ホームページ、ログインページ、登録ページ、忘れたパスワードページなど)、私が達成しようとしているものは、保護されていない特定のページがあります:AspectがSpringで実行されていません

  • ユーザーがログに記録されていない場合すでにログインしているユーザーは、 ホームページにリダイレクトする場合は、これらの非保護されたページにアクセスする際に、 は通常
  • をそれらを表示(またはredirectTo注釈要素で指定したページへ)もちろん

私はこれをすべての単一のコントローラメソッドに入れないようにしたい:

if(loggedIn()) 
{ 
    // Redirect 
} 
else 
{ 
    // Return the view 
} 

このため、私はAOPを使用したいと思います。

I注釈@NonSecuredを作成し、私は、次のアスペクト符号化:

@Aspect 
public class LoggedInRedirectAspect 
{ 
    @Autowired 
    private UserService userService; 

    @Around("execution(@my.package.annotation.NonSecured * *(..))") 
    public void redirect(ProceedingJoinPoint point) throws Throwable 
    { 
     System.out.println("Test"); 
     point.proceed(); 
    } 
} 

例注釈を付け方法:

@Controller 
@RequestMapping("/") 
public class HomeController 
{ 
    @NonSecured(redirectTo = "my-profile") 
    @RequestMapping(method = RequestMethod.GET) 
    public String index(Model model, 
         HttpServletRequest request) throws Exception 
    { 
     // Show home page 
    } 
} 

applicationContext.xmlを重要ビット:

<context:annotation-config /> 
<context:component-scan base-package="my.package" /> 

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> 

<bean id="loggedInRedirectAspect" class="my.package.aspect.LoggedInRedirectAspect" /> 
<aop:aspectj-autoproxy proxy-target-class="true"> 
    <aop:include name="loggedInRedirectAspect" /> 
</aop:aspectj-autoproxy> 

問題があるのその側面のメソッドredirect(...)は決してcalleを取得しないd。 一般的なアスペクトは正常に動作していますが、実際にはアスペクトの次のメソッドが呼び出されます:以下のアドバイスが呼び出されますが、コントローラメソッドが呼び出されることはありません。

@Around("execution(* *(..))") 
public void redirect(ProceedingJoinPoint point) throws Throwable 
{ 
    point.proceed(); 
} 

私のポイントカットに何か間違っていますか?

ありがとうございます。

更新:この質問の最後のスニペットが呼び出されますが、コントローラメソッドは呼び出されません。

答えて

6

@satoshi、私はあなたがSpring-AOPを使用しており、インターフェイスを持つBeanに対してのみAOPプロキシを作成でき、あなたの場合はコントローラがインターフェイスを持たないため問題があると思います。

修正はAspectJのを使用して、時間/負荷時間織りをコンパイルし、クラスパスにCGLIBの瓶を持っているとCGLIBベースのプロキシの作成を強制的に春AOP ORを使用しないように使用することができます

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

更新:

<plugin> 
    <groupId>org.codehaus.mojo</groupId> 
    <artifactId>aspectj-maven-plugin</artifactId> 
    <version>1.0</version> 
    <dependencies> 
     <dependency> 
      <groupId>org.aspectj</groupId> 
      <artifactId>aspectjrt</artifactId> 
      <version>1.6.10</version> 
     </dependency> 
     <dependency> 
      <groupId>org.aspectj</groupId> 
      <artifactId>aspectjtools</artifactId> 
      <version>1.6.10</version> 
     </dependency> 
    </dependencies> 
    <executions> 
     <execution> 
      <goals> 
       <goal>compile</goal> 
       <goal>test-compile</goal> 
      </goals> 
     </execution> 
    </executions> 
    <configuration> 
     <outxml>true</outxml> 
     <verbose>true</verbose> 
     <showWeaveInfo>true</showWeaveInfo> 
     <aspectLibraries> 
      <aspectLibrary> 
       <groupId>org.springframework</groupId> 
       <artifactId>spring-aspects</artifactId> 
      </aspectLibrary> 
     </aspectLibraries> 
     <source>1.6</source> 
     <target>1.6</target> 
    </configuration> 
</plugin> 
+0

@BijuKunjummenありがとう、これは問題を解決しませんでした – satoshi

+0

コントローラクラス@satoshiでブレークポイントでデバッグすることができます - あなたのケースのように、cglibでプロキシが正常に作成されている場合は、コントローラクラスのタイプ、デバッグ変数(Eclipseの場合)に反映されます。タイプがプロキシではないと思われる場合、CGLIBは有効ではありません。コンパイル時の織り方を使用することをお勧めします。ウィーバーの冗長オプションをオンにして、実際に織り込まれているクラスを確認してください。 –

+0

@BijuKunjummen、コントローラのためにプロキシが作成されないようです(タイプはHomeControllerなので、スタックトレースのプロキシ/ aopメソッドへの呼び出しを見ることはできません)。あなたが言うように、CGLIBは有効ではありません。私は申し訳ありませんが、私は春には新しく、コンパイル時にどのように役立ちますか?そして私はそれをどのように使うことができますか?ありがとうございました – satoshi

0

通常、私はインターセプタを使用し、この目的のための側面は使用しません。たとえば、セキュリティプリンシパルをチェックしてそれに応じてリダイレクトするRequestInitializeInterceptorを作成します。アスペクトはこの仕事の過労です。インターセプタは、特定のコントローラに対するすべての要求に対してフロントコントローラとして動作し、要求を転送するかどうかを決定します。

public class RequestInitializeInterceptor extends HandlerInterceptorAdapter { 

    // Obtain a suitable logger. 
    private static Log logger = LogFactory 
     .getLog(RequestInitializeInterceptor.class); 

    /** 
    * In this case intercept the request BEFORE it reaches the controller 
    */ 
    @Override 
    public boolean preHandle(HttpServletRequest request, 
     HttpServletResponse response, Object handler) throws Exception { 
    try { 

     logger.info("Intercepting: " + request.getRequestURI()); 

     // Your logic to redirect accordingly 
    if (userAuthenticated) { 
     response.sendRedirect(URL); 
     return false; 
    } 
     return true; 
    } catch (SystemException e) { 
     logger.info("request update failed"); 
     return false; 
    } 
    } 
} 

これが役立ちます。

+0

あなたの答え、@Abhiてくれてありがとう。私は重要な点を省いたと思う。 '@ NonSecured'アノテーションには" redirectTo "要素があります。ここでは、ユーザーが既にログインしているときにリクエストをリダイレクトする場所を指定できます。元の質問を更新しました。私はこの要求を受けてインターセプタをどのように使うことができないのか分かりません... – satoshi

+0

インターセプタはすべてのget要求をインターセプトし、ユーザーが認証されているかどうか、またユーザーの状態によって評価する要求からセキュリティプリンシパルを取得できます単純にresponse.sendredirectを実行してください – Abhi

+0

これは、インターセプタ内のすべての決定ロジックをコーディングする必要があることを意味し、それを行うのは非常に汚い方法だと思いますか?要求がリダイレクトを必要とするかどうかを検出するために 'if'をたくさん用意しています。 – satoshi

0

くれのために働いていた何を、してくださいC:時間織りは、Mavenプラグインを使用して行うことができますコンパイルし、showWeaveInfo構成が織り込まれていたクラスのかを正確に表示されます一体、以下の点:

  • aspectjweaver.jarがクラスパス上にある(バージョン1.6.8以降)
  • アスペクトクラスは@Aspect@Component
  • の両方で注釈されているあなたは春AspectJの-自動プロキシ
有効

Java設定:

@Configuration 
@ComponentScan("io.mc.springaspects") 
@EnableAspectJAutoProxy 
public class SpringConfiguration { 
} 

アスペクト:

@Aspect 
@Component 
public class AnnotationAspect { 
    ... 
} 

のMaven:

<dependency> 
    <groupId>org.aspectj</groupId> 
    <artifactId>aspectjweaver</artifactId> 
    <version>1.8.9</version> 
</dependency> 
関連する問題