Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring mvc 如何使@PreAuthorize具有高于@Valid或@Validated的优先级_Spring Mvc_Spring Security_Controller_Bean Validation_Role Base Authorization - Fatal编程技术网

Spring mvc 如何使@PreAuthorize具有高于@Valid或@Validated的优先级

Spring mvc 如何使@PreAuthorize具有高于@Valid或@Validated的优先级,spring-mvc,spring-security,controller,bean-validation,role-base-authorization,Spring Mvc,Spring Security,Controller,Bean Validation,Role Base Authorization,我使用的是spring boot,我已经通过 @EnableGlobalMethodSecurity(prePostEnabled = true, order = Ordered.HIGHEST_PRECEDENCE) 下面是我的控制器代码 @PreAuthorize("hasAnyRole('admin') or principal.id == id") @RequestMapping(value = "/{id}", method = RequestMethod.PUT) public

我使用的是spring boot,我已经通过

@EnableGlobalMethodSecurity(prePostEnabled = true, order = Ordered.HIGHEST_PRECEDENCE) 
下面是我的控制器代码

@PreAuthorize("hasAnyRole('admin') or principal.id == id")
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public User updateUser(@PathVariable("id") String id,  @Valid @RequestBody   UserDto userDto) 
{ ....}
但是,当非管理员用户尝试执行PUT请求时,JSR303验证程序将在@PreAuthorize之前启动。 例如,非管理员用户最终得到的结果是“需要名字”而不是“拒绝访问”。但在用户提供第一个name变量以通过验证程序后,返回了拒绝访问

有人知道如何在@Valid或@Validated之前执行@PreAuthorize-get-check吗


为了执行一些复杂的规则检查,我必须使用这种方法级授权,而不是基于url的授权。

对于相同的场景,我发现了通过spring筛选器实现安全性的建议。
下面是类似的帖子:

另外,可能还有一种不同的方法-尝试通过在@InitBinder中注册自定义验证器来使用验证(从而跳过@valid注释)

要访问筛选器类中的主体对象,请执行以下操作:

  SecurityContextImpl sci = (SecurityContextImpl)     
session().getAttribute("SPRING_SECURITY_CONTEXT");

if (sci != null) {
    UserDetails cud = (UserDetails) sci.getAuthentication().getPrincipal();

 }
在本例中,/{id}是URL中的路径参数。要访问筛选器或侦听器类中的路径参数,请执行以下操作:

String[] requestMappingParams =    ((HandlerMethod)handler).getMethodAnnotation(RequestMapping.class).params()

        for (String value : requestMappingParams) {.

我也有同样的问题,我找到了这篇文章。戴纳姆先生的评论帮助我了解出了什么问题

以下是我所做的:

  • public方法具有@PreAuthorize并执行检查
  • @RequestBody参数上没有@Valid
  • 我创建了第二个方法private,在这里我进行DTO验证。使用@Valid注释
  • 公共方法将调用委托给私有方法。只有当公共方法被授权时,才会调用私有方法
  • 例如:

    @RequestMapping(method = RequestMethod.POST)
    @PreAuthorize("hasRole('MY_ROLE')")
    public ResponseEntity createNewMessage(@RequestBody CreateMessageDTO createMessageDTO) {
        // The user is authorized
        return createNewMessageWithValidation(createMessageDTO);
    }
    
    private ResponseEntity createNewMessageWithValidation(@Valid CreateMessageDTO createMessageDTO) {
       // The DTO is valid
       return ...
    }
    

    使用
    websecurityConfigureAdapter.configure(HttpSecurity http)
    而不是
    @PreAuthorize

    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter
    {
      @Override
      protected void configure(HttpSecurity http) throws    Exception {
        http
          .authorizeRequests()
          .mvcMatchers( "/path/**").hasRole("admin");
      }
    }
    

    谢谢,我也看到了那篇文章,但是spring过滤器(基于url)在我的案例中不起作用,因为我需要使用url参数对主体ID进行验证。我在实现中使用了@InitBinder,但在验证程序之前仍然没有调用@PreAuthorize。您可以访问servlet筛选器中的主体对象。这有帮助吗?我在servlet筛选器类中添加了一个访问prinicipal对象的代码段。我不确定这是否会让您更容易…谢谢,我以前从未使用过servlet fitler。假设我的一个REST PUT请求是/user/{id},我只允许用户编辑自己的帐户。如何检查筛选器中的{id}?例如,用户id=2只允许对/user/2而不是/user/3发出PUT请求?哦,我明白了。好的,我添加了一些代码,说明如何从请求对象访问path param/{id}。我想这会奏效的。希望有帮助!这永远不会发生。只有在执行方法时才会调用
    @PreAuthorize
    。但是,
    @Valid
    是在准备执行方法时处理的,这发生在方法实际执行之前。所以这行不通。作为一种解决方法,您可以进行手动验证,而不是依赖
    @Valid
    注释。我明白了。感谢您在后台解释它是如何工作的。我认为,如果他们将来能够在预授权后支持验证,那将是一件好事。这将很困难,因为这将改变AOP的整个工作方式:)。我可以看到映射URL和增加安全性的改进。目前只使用了ant风格的表达式和正则表达式,但是我可以看到人们可能也希望使用路径变量来实现安全性。有没有干净的解决方案?