Spring Security可以在Spring控制器方法上使用@PreAuthorize吗?

时间:2010-06-21 18:53:26

标签: java spring-mvc controller spring-security

Spring Security可以在Spring控制器方法上使用@PreAuthorize吗?

8 个答案:

答案 0 :(得分:68)

是的,它运作正常。

<security:global-method-security pre-post-annotations="enabled" />中需要...-servlet.xml。它还需要CGLIB proxies,因此您的控制器不应该有接口,或者您应该使用proxy-target-class = true

答案 1 :(得分:23)

Spring Security FAQ(强调我的)。

  

在Spring Web应用程序中,持有的应用程序上下文   调度程序servlet的Spring MVC bean通常是独立的   主要应用背景。它通常在一个名为的文件中定义   myapp-servlet.xml,其中“myapp”是分配给Spring的名称   web.xml中的DispatcherServlet。一个应用程序可以有多个   DispatcherServlets,每个都有自己独立的应用程序上下文。   这些“子”环境中的bean对于其余部分是不可见的   应用。 “父”应用程序上下文由   您在web.xml中定义的ContextLoaderListener,对所有人都可见   孩子的背景。此父上下文通常是您定义的位置   您的安全配置,包括   元件)。因此,任何安全约束都应用于方法中   由于无法看到bean,因此不会强制执行这些Web Bean   来自DispatcherServlet上下文。你需要移动    声明到Web上下文或移动了   您想要保护到主应用程序上下文中的bean。

     

通常我们建议在服务中应用方法安全性   层而不是单个Web控制器。

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

答案 2 :(得分:17)

如果你使用的是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";
}

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

答案 3 :(得分:9)

自问这个问题以来已经过去了两年多,但由于我今天遇到的问题,我宁愿不鼓励在{{1}上使用@Secured@PreAuthorize等}第

对我来说不起作用的是@Controller@Validated控制器相结合:

@Secured

Validator根本不会触发(Spring MVC 4.1.2,Spring Security 3.2.5)并且不执行任何检查。

类似的问题是由Spring使用的CGLIB代理引起的(当没有类实现接口时,Spring创建CGLIB代理;如果类实现任何接口,则生成JDK代理 - documentation,{{3 }和well explained here)。

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

如果您想保护Web控制器,最好的想法是使用绑定到特定URL的@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) { // ... } <http>而不是控制器中的方法,并且工作得很好。就我而言:

<intercept-url />

答案 4 :(得分:5)

已经有关于如何通过更改xml配置使其工作的回复;但是,如果您正在使用基于代码的配置,则可以通过在@Configuration类上放置以下注释来实现相同的目的:

@EnableGlobalMethodSecurity(prePostEnabled=true)

答案 5 :(得分:1)

要扩展Andy提供的答案,您可以使用:

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

检查具体角色。

答案 6 :(得分:0)

首先,您需要在WebSecurityConfig中添加此批注以启用@Pre和@Post批注。

    @EnableGlobalMethodSecurity(prePostEnabled = true)

您还可以按以下方式检查角色/权限

    @PreAuthorize("hasAuthority('ROLE_ADMIN')")

等同于

    @PreAuthorize("hasRole('ROLE_ADMIN')")

您还可以如下检查多个角色/权限

    @PreAuthorize("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_USER') or ...")

答案 7 :(得分:0)

步骤1:在SecurityConfig类中添加 @EnableGlobalMethodSecurity(prePostEnabled = true)批注。 像这样:

 @Configuration
 @EnableWebSecurity
 @EnableGlobalMethodSecurity(prePostEnabled = true)
 public class SecurityConfig extends WebSecurityConfigurerAdapter {
   .....
 }

步骤2:,您可以在控制器或服务或存储库层中添加 @PreAuthorize()批注。在方法或类级别。 例如:

@RestController
@PreAuthorize("isAuthenticated()")    
public class WebController {  
  
    @PreAuthorize("permitAll()")  
    @GetMapping("/")  
    public String home() {  
        return "Welcome home!";  
    }

    @GetMapping("/restricted")   
    public String restricted() {  
        return "restricted method";  
    }
}

@RestController    
public class AdminController {
   
   
   @PreAuthorize("hasRole('ADMIN')")
   @GetMapping("/admin")
   public String adminMethod() {
   }
}