Spring security 6.0 AuthorizationFilter - ShouldFilterAllDispatcherTypes 的默认值有问题

Jür*_*hen 7 authorization exception spring-security spring-boot spring-restcontroller

今天我花了几个小时来解决向 Spring security 6.0 的迁移问题,将已弃用的authorizeRequests()方法替换为authorizeHttpRequests(). 我了解到,在幕后,这意味着用安全链中的FilterSecurityInterceptor新内容替换旧内容。但是,如果您尝试注册数据库中已存在的用户 ,我未经身份验证的注册端点已经得到了一些意外结果,该端点使用 JPA 验证的请求正文,并且还以 BadRequest = 400 进行应答。AuthorizationFilter
@Valid

当转向 AuthorizationFilter 时,有效的注册请求仍然按预期工作,但错误情况(验证失败以及已存在的用户)均回复 Unauthorized = 401,这对于未经身份验证的端点来说是不可接受的...

我可以通过链接解决这个问题(最终!)

.shouldFilterAllDispatcherTypes(false)
Run Code Online (Sandbox Code Playgroud)

authorizeHttpRequests()

但现在我开始想知道,新的默认行为是否有意义......

相当不起眼的代码片段是:

  1. 控制器映射的调用,其中服务可以抛出@ResponseStatus(HttpStatus.BAD_REQUEST)带注释的UserAlreadyExistsException
@PostMapping("/api/register")
public ResponseEntity<Void> registerUser(@Valid @RequestBody UserDto userDto) {
    service.registerUser(mapper.toEntity(userDto));
    return ok().build();
}
Run Code Online (Sandbox Code Playgroud)
  1. SecurityFilterChain bean 的相关部分:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http,
                                               AuthenticationManager authenticationManager) throws Exception {
    http.authenticationManager(authenticationManager)
            //.authorizeRequests()  <-- deprecated, but working, using SecurityFilterInterceptor
            .authorizeHttpRequests()
            .shouldFilterAllDispatcherTypes(false) // without this line weird behavior since default is true
            .requestMatchers(HttpMethod.POST,"/api/register").permitAll()
            // ... more requestMatchers and other stuff
}
Run Code Online (Sandbox Code Playgroud)

因此,我深入研究了 AuthorizationFilter - 如果您查看 Spring Security 6.0.1 中的以下代码片段,Javadoc 已经是矛盾的AuthorizationFilter。第一个新方法的默认值与下面 3 个方法的默认值相矛盾:

/**
 * Sets whether to filter all dispatcher types.
 * @param shouldFilterAllDispatcherTypes should filter all dispatcher types. Default
 * is {@code true}
 * @since 5.7
 */
public void setShouldFilterAllDispatcherTypes(boolean shouldFilterAllDispatcherTypes) {
   this.observeOncePerRequest = !shouldFilterAllDispatcherTypes;
   this.filterErrorDispatch = shouldFilterAllDispatcherTypes;
   this.filterAsyncDispatch = shouldFilterAllDispatcherTypes;
}
//...

/**
 * Sets whether this filter apply only once per request. By default, this is
 * <code>true</code>, meaning the filter will only execute once per request. Sometimes
 * users may wish it to execute more than once per request, such as when JSP forwards
 * are being used and filter security is desired on each included fragment of the HTTP
 * request.
 * @param observeOncePerRequest whether the filter should only be applied once per
 * request
 */
public void setObserveOncePerRequest(boolean observeOncePerRequest) {
   this.observeOncePerRequest = observeOncePerRequest;
}

/**
 * If set to true, the filter will be applied to error dispatcher. Defaults to false.
 * @param filterErrorDispatch whether the filter should be applied to error dispatcher
 */
public void setFilterErrorDispatch(boolean filterErrorDispatch) {
   this.filterErrorDispatch = filterErrorDispatch;
}

/**
 * If set to true, the filter will be applied to the async dispatcher. Defaults to
 * false.
 * @param filterAsyncDispatch whether the filter should be applied to async dispatch
 */
public void setFilterAsyncDispatch(boolean filterAsyncDispatch) {
   this.filterAsyncDispatch = filterAsyncDispatch;
}

Run Code Online (Sandbox Code Playgroud)

更糟糕的是,如果您使用默认值,似乎存在绕过授权的相关漏洞,如下面的链接所述。所以我想知道, default=true for 是否shouldFilterAllDispatcherTypes有意义 - 或者我在这里错过了一点吗?
https://security.snyk.io/vuln/SNYK-JAVA-ORGSPRINGFRAMEWORKSECURITY-3092126

Nik*_*tov 0

我不确定这是否能回答您的问题,但您正在使用 AuthorizationManagerRequestMatcherRegistry 并且您正在查看 AuthorizationFilter。在这里检查此链接: 来源

/**
     * Sets whether all dispatcher types should be filtered.
     * @param shouldFilter should filter all dispatcher types. Default is {@code true}
     * @return the {@link AuthorizationManagerRequestMatcherRegistry} for further
     * customizations
     * @since 5.7
     */
    public AuthorizationManagerRequestMatcherRegistry shouldFilterAllDispatcherTypes(boolean shouldFilter) {
        this.shouldFilterAllDispatcherTypes = shouldFilter;
        return this;
    }
Run Code Online (Sandbox Code Playgroud)