2012-07-09 51 views
1

我試圖讓Spring MVC應用與Spring @Secured註解和AspectJ自動代理一起玩,但它似乎並沒有代理或識別我的@Secured註釋。我有一個這樣的控制器:@Secured註解不能在AspectJ模式下使用Autoproxy

@Controller 
@RequestMapping("/") 
public class ApplicationController { 

    private ApplicationFactory applicationFactory; 

    @Inject 
    public ApplicationController(ApplicationFactory applicationFactory) { 
     super(); 
     this.applicationFactory = applicationFactory; 
    } 

    @Secured("ROLE_USER") 
    @ResponseBody 
    @RequestMapping(method = GET) 
    public Application getApplicationInfo() { 
     return applicationFactory.buildApplication(this); 
    } 

} 

和彈簧安全XML,看起來是這樣的:

代碼:

<security:global-method-security secured-annotations="enabled" mode="aspectj" proxy-target-class="true" /> 

    <security:http auto-config="true" use-expressions="true"> 
    <security:http-basic/> 
    </security:http> 

以上是由無XML彈簧加載@像這樣的配置組件:

@Configuration 
@ComponentScan(basePackages = {"com.example"}) 
@EnableWebMvc 
@ImportResource("classpath:security.xml") 
public class ApplicationConfiguration extends WebMvcConfigurerAdapter { 

} 

然後使用Servlet 3.0 WebApplicationI nitializer:

public class SpringMvcInitializer implements WebApplicationInitializer { 

    private final AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); 

    public void onStartup(ServletContext servletContext) throws ServletException { 
     context.register(ApplicationConfiguration.class); 

     servletContext.addListener(new ContextLoaderListener(context)); 
     servletContext.addListener(new Log4jConfigListener()); 

     final DelegatingFilterProxy proxy = new DelegatingFilterProxy("springSecurityFilterChain", context); 
     FilterRegistration.Dynamic filter = servletContext.addFilter("securityFilter", proxy); 
     filter.addMappingForUrlPatterns(EnumSet.of(REQUEST), false, "/*"); 

     final DispatcherServlet servlet = new DispatcherServlet(context); 
     ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", servlet); 
     dispatcher.setLoadOnStartup(1); 
     dispatcher.addMapping("/*"); 
    } 

} 

然而,Spring Security中沒有檢測到的註釋,我仍然能夠上方端點安全不被認可。根據Spring Security FAQ,這可能是因爲<global-method-security>元素正在加載錯誤的應用程序上下文中,但我不知道如何確保使用上述no-xml Spring配置。

我錯過了什麼嗎?我嘗試將@EnableAspectJAutoProxy(proxyTargetClass = true)添加到我的應用程序配置中,但這也沒有幫助。是否有運行時編織或我將不得不使用編譯時編織來爲我的應用程序啓用基於註釋的安全性?

+1

你究竟想達到什麼目的?你爲什麼需要'mode =「aspectj」'? – axtavt 2012-07-09 18:13:50

+0

我試圖使用@Secured註釋與自動代理,而無需加載/編譯時織入。 – 2012-07-09 18:30:25

回答

5

當使用AOP使用Spring,你可以AOP的兩種實現方式之間進行選擇:

  • Spring AOP的實現並不需要編織和,但它僅適用於由Spring管理豆some limitations

  • AspectJ AOP實現可以適用於所有對象,並且沒有Spring AOP的限制,但需要編譯時或加載時編織

mode="aspectj"告訴Spring使用AspectJ進行AOP實現,因此如果沒有編織,安全性方面將不起作用。

術語「AspectJ自動代理」與使用AspectJ作爲AOP實現無關 - 它允許您在Spring AOP中使用AspectJ API(而不是實現)。

因此,您的情況可以使用Spring AOP實現,因爲控制器是Spring bean,因此您應該刪除mode="aspectj"。還要注意你的控制器應該沒有參數構造函數 - 這是Spring AOP的限制之一。

+0

你是對的,現在修好了。它的恥辱Spring AOP CGLIB自動代理不支持構造函數注入。 – 2012-07-09 19:00:56

+1

@RicardoGladwell:它的確如此,除了'@Inject'構造函數之外,您只需要創建無參數構造函數。 – axtavt 2012-07-09 19:04:44

+0

它是否必須是公共構造函數? – 2012-07-09 19:20:51

3

爲了擴大對@ axtavt的回答了一下,global-method-securitymode="aspectj"選項明確要求你的代碼已經被編織與AnnotationSecurityAspectspring-security-aspects模塊。

有一些sample code它演示了它的使用。它只包含一個安全的bean和一些Junit測試,但代碼是用AspectJ編譯器編譯的。application context也顯示了與添加名稱空間支持(註釋掉的bean)之前所需的內容相比,它的簡單性。

相關問題