为什么我在设置permitAll时会收到来自Spring-Security的403?

lymgl2op  于 2023-08-05  发布在  Spring
关注(0)|答案(2)|浏览(145)

我有以下代码:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests((authz) -> authz
            .requestMatchers("/actuator/**").permitAll()
            .requestMatchers("/h2-console/**").permitAll()
            .anyRequest().authenticated()
    );
    http.csrf(AbstractHttpConfigurer::disable);
    http.headers((headers) -> headers
            .frameOptions((frame) -> frame
                    .disable()
            )
    );
    return http.build();
}

字符串
但是当我尝试访问h2-console端点时,我收到一个403错误:

curl -v http://localhost:8080/h2-console
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
...
* Mark bundle as not supporting multiuse
< HTTP/1.1 403


如果我将authenticated修改为permitAll,即.anyRequest().permitAll(),它的功能完全正常。
如何配置代码以限制对h2-console及其所有子路径的访问,但阻止对所有其他路径的访问?

更新

根据建议,我尝试了这个...

@Configuration
public class AppConfig {
    private static RequestMatcher h2ConsoleRequestMatcher() {
        return new RequestMatcher() {
            @Override
            public boolean matches(HttpServletRequest request) {
                String path = request.getServletPath();
                return path.startsWith("/h2-console");
            }
        };
    }
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        // TODO: 2021-10-13 - remove permitAll() and add proper security
        http.authorizeHttpRequests((authz) -> authz
                .requestMatchers("/actuator/**").permitAll()
                .requestMatchers("/h2-console/**").permitAll()
                .anyRequest().authenticated()
        );
        http.csrf((csrf) ->
                csrf.ignoringRequestMatchers(h2ConsoleRequestMatcher())
                        .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        );
        http.headers((headers) -> headers
                .frameOptions(
                        HeadersConfigurer.FrameOptionsConfig::disable
                )
        );
        return http.build();
    }
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.setAllowCredentials(true);
        corsConfig.addAllowedOrigin("http://localhost:3000");
        corsConfig.addAllowedHeader("*");
        corsConfig.addAllowedMethod("*");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfig);

        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}


但我还是拿到了403...

curl http://localhost:8080/h2-console -v
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /h2-console HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.87.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 403


感谢下面接受的答案这里是最终的工作版本

@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((authz) -> authz
                .requestMatchers(new AntPathRequestMatcher("/actuator/**")).permitAll()
                .requestMatchers(new AntPathRequestMatcher("/h2-console/**")).permitAll()
                .anyRequest().authenticated()
        );
        http.csrf((csrf) ->
                csrf.ignoringRequestMatchers(new AntPathRequestMatcher("/h2-console/**"))
                        .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        );
        http.headers((headers) -> headers
                .frameOptions(
                        HeadersConfigurer.FrameOptionsConfig::disable
                )
        );
        return http.build();
    }

bcs8qyzn

bcs8qyzn1#

默认情况下,requestMatchers("a_string_path")将Map到MvcRequestMatcher
如果HandlerMappingIntrospector在类路径中可用,则Map到不关心使用哪个HttpMethod的MvcRequestMatcher。这个匹配器将使用Spring MVC用于匹配的相同规则。例如,路径**"/path”的Map经常会匹配"/path”、“/path/""/path.html”**等。如果HandlerMappingIntrospector不可用,则Map到AntPathRequestMatcher。如果必须指定特定的RequestMatcher,请使用requestMatchers(RequestMatcher...)代替Params:模式-要匹配的模式。如果使用MvcRequestMatcher,则匹配规则由Spring MVC定义返回:创建RequestMatcher后链接的对象。自:5.8
因此,要使用自己的Servlet访问
h2-console
,需要使用AntPathRequestMatcher
这应该可以工作:

.requestMatchers(new AntPathRequestMatcher("/h2-console/**")).permitAll()

字符串
另一种方法是提供一个额外的WebSecurityCustomizer bean。

@Bean
//@Profile("dev")
WebSecurityCustomizer h2ConsoleSecurityCustomizer() {
 return web -> 
      web.ignoring().requestMatchers(new AntPathRequestMatcher("/h2-console/**"));
}

yquaqz18

yquaqz182#

发生此行为是因为默认的Spring Security配置包括针对CSRF攻击的保护,并且/h2-console端点受此保护的影响。启用CSRF保护时,对/h2控制台端点的请求需要包含有效的CSRF令牌。
要解决此问题,您可以配置Spring Security以使/h2-console端点免受CSRF保护。
将其添加到SecurityFilterChain中以禁用csrf:

http.csrf((csrf) -> csrf
                .ignoringAntMatchers("/h2-console/**")
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
);

字符串

相关问题