如何使@PreAuthorize具有比@Valid或@Validated更高的优先级

时间:2015-03-08 05:18:57

标签: spring-mvc spring-security controller bean-validation role-base-authorization

我正在使用spring boot,我已通过

在WebSecurityConfigurerAdapter中启用了全局方法安全性
@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之前启动。 例如,非管理员用户最终得到类似"首字母是必需的"而不是"访问被拒绝"。但是在用户提供了第一个名称变量以通过验证器之后,返回了拒绝访问。

有人知道在@Valid或@Validated之前如何强制执行@PreAuthorize检查?

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

3 个答案:

答案 0 :(得分:3)

我有同样的问题,我找到了这篇文章。 M. Deinum的评论帮助我理解出了什么问题

这是我做的:

  1. 公共方法具有@PreAuthorize并执行检查
  2. @RequestBody参数
  3. 上有 NO @Valid
  4. 我创建了第二个私有方法,我 DTO验证。使用@Valid注释
  5. 公共方法将调用委托给私有方法。仅在公共方法被授权的情况下调用私有方法
  6. 示例:

    changing

答案 1 :(得分:0)

对于同样的情况,我发现了通过弹簧过滤器实现安全性的建议 以下是类似的帖子:How to check security acess (@Secured or @PreAuthorize) before validation (@Valid) in my Controller?

另外,也许是一种不同的方法 - 尝试通过在@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) {.

答案 2 :(得分:0)

使用WebSecurityConfigurerAdapter.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");
  }
}