为什么在设置 permitAll 时,Spring-Security 返回 403?

huangapple go评论55阅读模式
英文:

Why am I getting a 403 from Spring-Security when setting permitAll?

问题

以下是您要翻译的代码部分:

@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();
}

您还可以参考以下的最终工作版本代码:

@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();
}

请注意,上述代码已经经过修改以解决您的问题。

英文:

I have the following code:

@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();
}

but when I attempt to hit the h2-console endpoint, I receive a 403 error:

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 

If I modify the authenticated to permitAll, i.e., .anyRequest().permitAll(), it functions perfectly fine.

How can I configure the code to restrict access to h2-console and all its sub-paths but is blocked for all other paths?

Update

Per the suggestion I tried this...

@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;
    }
}

But I still get the 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 

Thanks to the accepted answer below here is the final working version

    @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();
    }

答案1

得分: 1

默认情况下,requestMatchers("a_string_path") 将映射到一个 MvcRequestMatcher

如果 HandlerMappingIntrospector 在类路径中可用,将映射到一个不关心使用哪种 HttpMethod 的 MvcRequestMatcher。此匹配器将使用Spring MVC用于匹配的相同规则。例如,通常情况下,路径 "/path" 的映射将匹配 "/path""/path/""/path.html" 等。如果没有可用的HandlerMappingIntrospector,则映射到AntPathRequestMatcher。

如果需要指定特定的RequestMatcher,请改用 requestMatchers(RequestMatcher...)

参数:
patterns – 要匹配的模式。如果使用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/**"));
}
英文:

By default, requestMatchers("a_string_path") will map to a MvcRequestMatcher

>If the HandlerMappingIntrospector is available in the classpath, maps to an MvcRequestMatcher that does not care which HttpMethod is used. This matcher will use the same rules that Spring MVC uses for matching. For example, often times a mapping of the path "/path" will match on "/path", "/path/", "/path.html", etc. If the HandlerMappingIntrospector is not available, maps to an AntPathRequestMatcher.
If a specific RequestMatcher must be specified, use requestMatchers(RequestMatcher...) instead
Params:
patterns – the patterns to match on. The rules for matching are defined by Spring MVC if MvcRequestMatcher is used
Returns:
the object that is chained after creating the RequestMatcher.
Since:
5.8

So for accessing the h2-console with its own Servlet, you need to use an AntPathRequestMatcher

This should work:

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

An alternative is to provide a extra WebSecurityCustomizer bean.

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

答案2

得分: 0

这种行为发生是因为默认的Spring Security配置包括对CSRF攻击的保护,而/h2-console端点受到这种保护的影响。当启用CSRF保护时,对/h2-console端点的请求需要包含有效的CSRF令牌。

要解决这个问题,您可以配置Spring Security以免除/h2-console端点免受CSRF保护。

将以下内容添加到您的SecurityFilterChain以禁用CSRF:

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

这将禁用对/h2-console端点的CSRF保护。

英文:

This behavior occurs because the default Spring Security configuration includes protection against CSRF attacks, and the /h2-console endpoint is affected by this protection. When CSRF protection is enabled, the requests to the /h2-console endpoint require a valid CSRF token to be included.

To resolve this issue, you can configure Spring Security to exempt the /h2-console endpoint from CSRF protection.

Add this into your SecurityFilterChain to disable the csrf :

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

huangapple
  • 本文由 发表于 2023年6月16日 10:02:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76486531.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定