春季安全可以在Spring控制器方法上使用@PreAuthorize吗?

春季安全可以在Spring控制器方法上使用@PreAuthorize吗?

是的,它工作正常。

...-servlet.xml需要<security:global-method-security pre-post-annotations="enabled" /> 。 它也需要CGLIB代理 ,所以你的控制器不应该有接口,或者你应该使用proxy-target-class = true

请参阅Spring Security FAQ (重点介绍我的)。

在Spring Web应用程序中,为调度程序servlet保存Spring MVC bean的应用程序上下文通常与主应用程序上下文分离。 它通常在名为myapp-servlet.xml的文件中定义,其中“myapp”是在web.xml中分配给Spring DispatcherServlet的名称。 应用程序可以有多个DispatcherServlet,每个DispatcherServlet都有自己的独立应用程序上下文。 这些“子”上下文中的bean对应用程序的其余部分是不可见的。 “父”应用程序上下文由您在web.xml中定义的ContextLoaderListener加载,并且对于所有子上下文都是可见的。 这个父上下文通常是你定义安全configuration的地方,包括元素)。 因此,应用于这些Web Bean中的方法的安全约束将不会被强制执行,因为无法从DispatcherServlet上下文中看到Bean。 您需要将声明移至Web上下文,或者将需要保护的bean移动到主应用程序上下文中。

一般来说,我们会build议在服务层而不是单独的networking控制器上应用方法安全性。

如果将切入点应用于服务层,则只需在应用程序的安全上下文中设置<global-method-security>

如果你使用的是Spring 3.1,那么你可以用一些非常酷的东西。 看看https://github.com/mohchi/spring-security-request-mapping 。 这是一个示例项目,它将@PreAuthorize与Spring MVC的RequestMappingHandlerMapping集成在一起,以便您可以执行如下操作:

 @RequestMapping("/") @PreAuthorize("isAuthenticated()") public String authenticatedHomePage() { return "authenticatedHomePage"; } @RequestMapping("/") public String homePage() { return "homePage"; } 

如果用户通过身份validation,则请求“/”将调用authenticatedHomePage()。 否则,它会调用homePage()。

这个问题已经过了两年多了,但是由于我今天遇到的问题,我宁愿不鼓励在@Controller上使用@Controller @PreAuthorize@Controller @PreAuthorize等。

什么没有为我工作@Validated结合@Secured控制器:

 @Controller @Secured("ROLE_ADMIN") public class AdministrationController { // @InitBinder here... @RequestMapping(value = "/administration/add-product", method = RequestMethod.POST) public String addProductPost(@ModelAttribute("product") @Validated ProductDto product, BindingResult bindingResult) { // ... } 

validation器不会触发(Spring MVC 4.1.2,Spring Security 3.2.5)并且不执行检查。

类似的问题是由Spring使用的CGLIB代理引起的(当没有接口实现类时,Spring创buildCGLIB代理;如果类实现了任何接口,则生成JDK代理 – 文档 , 在这里和这里都有详细说明 )。

正如我在上面链接的答案中所提到的那样,最好是在通常实现接口的服务层上使用Spring Security注释(因此使用JDK代理),因为这不会导致这样的问题。

如果你想保护web控制器,最好的办法是使用<http><intercept-url />绑定到特定的URL而不是控制器中的方法,并且工作得很好。 在我的情况下:

 <http use-expressions="true" disable-url-rewriting="true"> ... <intercept-url pattern="/administration/**" access="hasRole('ROLE_ADMIN')" /> </http> 

为了延伸Andy提供的答案,您可以使用:

 @PreAuthorize("hasRole('foo')") 

检查具体的作用。

关于如何通过更改xmlconfiguration使其工作已经有了答案,但是,如果您正在使用基于代码的configuration,则可以通过在您的@Configuration类中添加以下注释来实现同样的效果: @EnableGlobalMethodSecurity(prePostEnabled=true)