2012-02-16 8 views
2

저는 로그인으로 거의 완벽하게 보호 될 웹 사이트를 코딩하고 있습니다. (저는 Spring Security를 ​​사용하고 있습니다). 비록 (홈 페이지, 로그인 페이지, 등록 페이지, 잊어 버린 암호 페이지 등) 어떤 보호를받지 못하는 페이지가 있습니다. 내가 이루고자하는 목표는 다음과 같습니다.Aspect가 Spring에서 실행되지 않았습니다.

  • 사용자가 기록되지 않은 경우 이미 로그인 한 사용자의 홈 페이지로 리디렉션 경우이 보안되지 않은 페이지에 액세스 할 때에, 는 일반적으로
  • 을 그들에게 보여 (또는 redirectTo 주석 요소에 지정된 페이지) 물론

나는 이것을 모든 단일 컨트롤러 방법에 넣는 것을 피하고 싶다 :

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

그런 이유로 나는 AOP를 사용하고 싶습니다.

난 주석 @NonSecured 생성 및 I는 다음의 화면으로 구분 :

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

이 문제를 aspect 내의 메소드 redirect(...)가 결코 calle을 얻지 못한다고 디. 일반적으로 aspect는 잘 동작하고 있습니다. 실제로 aspect의 다음 메소드가 호출됩니다 : 다음 advice가 호출되지만 컨트롤러 메소드는 호출되지 않습니다.

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

내 포인트 컷에 문제가 있습니까?

감사합니다.

업데이트 :이 질문의 마지막 스 니펫이 호출되지만 컨트롤러 메서드는 여전히 호출되지 않습니다.

답변

6

@satoshi, 당신이 가진 문제는 Spring-AOP를 사용하고 있으며 인터페이스가있는 빈에 대해서만 AOP 프록시를 만들 수 있기 때문이라고 생각합니다. 귀하의 경우 컨트롤러에는 인터페이스가 없습니다.

수정은 AspectJ를을 사용하여 직조 시간/부하 컴파일 시간을 사용할 수와 Spring AOP를 사용하지 않는 또는 클래스 패스에 CGLIB의 항아리를 가지고와 CGLIB 기반의 프록시 생성을 강제로 :

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

업데이트 : 시간 직물이 받는다는 플러그인을 사용하여 수행 할 수 있습니다을 컴파일의 showWeaveInfo 구성은 정확히 클래스 중 어느 길쌈 된 표시됩니다 :

<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는 효과가 없습니다 - 컴파일 시간 짜기를 사용하는 것이 좋습니다 - 그러면 위버의 장황한 옵션을 켜서 실제로 어떤 클래스가 weaved되는지 알아 보겠습니다 –

+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

감사합니다. 나는 중요한 부분을 생략했다. '@ NonSecured' 주석은 사용자가 이미 로그인했을 때 요청을 재지 정할 위치를 지정할 수있는 "redirectTo"요소를 가지고 있습니다. 원래 질문을 업데이트했습니다. 이 요구 사항이 주어진다면 인터셉터를 어떻게 사용할 수 있을지 모르겠다. ... – satoshi

+0

인터셉터는 모든 get 요청을 인터셉트하고 사용자가 인증되었는지 여부와 사용자 상태에 따라 평가할 요청에서 보안 주체를 가져올 수있다 단순히 response.sendredirect를 수행하십시오 – Abhi

+0

하지만 이것은 모든 요격 논리를 인터셉터에 코드화해야한다는 것을 의미하며, 그렇게하는 것은 매우 더러운 방법이라고 생각합니까? 요청에 리다이렉트가 필요한지를 감지하기 위해'if'를 많이 가지고 있습니다 ... – satoshi

0

, 제발 C에 근무 무엇 도대체 다음 사항 :

  • aspectjweaver.jar는 클래스 패스 (버전 1.6.8 이상)
  • 화면 클래스의 주석을 붙일에 모두 @Aspect
  • 당신 활성화 봄 AspectJ를-자동 프록시
@Component

자바 설정 :

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

화면 :

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

메이븐 : 당신의 대답, @Abhi에 대한

<dependency> 
    <groupId>org.aspectj</groupId> 
    <artifactId>aspectjweaver</artifactId> 
    <version>1.8.9</version> 
</dependency> 
관련 문제