You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3启用Basic Auth后CPU占用过高问题求助

问题描述

我有一个基于Spring Boot 3构建的Java应用,安全配置代码如下:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    private static final String[] permitMethods = new String[]{
            "/api/games/**",
            "/swagger-ui/**",
            "/v3/api-docs/**",
            "/actuator/**"
    };

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable())
                .authorizeRequests(authorizeRequests ->
                        authorizeRequests
                                .requestMatchers(permitMethods).permitAll()
                                .anyRequest().authenticated()
                )
                .userDetailsService(userDetailsService())
                .httpBasic(Customizer.withDefaults());
        return http.build();
    }
    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
                .username("admin")
                .password("admin")
                .build();
        return new CachingUserDetailsService(new InMemoryUserDetailsManager(user));
    }

}

执行压测时,仅用40个并行线程,应用CPU占用率就超过70%,线程数越多CPU占用越高。但移除.httpBasic(Customizer.withDefaults());配置后,CPU占用率直接降至10%。当前使用Spring Boot 3.1.1版本,尝试过3.0.0版本,结果一致。需要在保留Basic Auth的前提下降低CPU占用。

优化方案

1. 替换默认密码编码器

User.withDefaultPasswordEncoder()默认使用的BCryptPasswordEncoder是高开销的哈希算法,设计目的是抵御暴力破解,但高并发场景下会大量消耗CPU。可以根据场景替换为更高效的编码器:

  • 测试环境:使用NoOpPasswordEncoder(明文校验,仅用于测试)
  • 生产环境:使用Argon2PasswordEncoder(安全性高且性能优于BCrypt)

示例代码:

@Bean
public PasswordEncoder passwordEncoder() {
    // 生产环境推荐Argon2
    return new Argon2PasswordEncoder();
    // 测试环境可使用NoOp
    // return NoOpPasswordEncoder.getInstance();
}

@Bean
public UserDetailsService userDetailsService() {
    UserDetails user = User.builder()
            .username("admin")
            .password(passwordEncoder().encode("admin"))
            .build();
    return new CachingUserDetailsService(new InMemoryUserDetailsManager(user));
}

2. 开启认证结果缓存

默认HTTP Basic不会缓存认证结果,每个请求都要重复解析Authorization头并校验用户信息。通过配置SecurityContextRepository实现认证结果缓存,减少重复校验开销:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
            .csrf(csrf -> csrf.disable())
            .authorizeRequests(authorizeRequests ->
                    authorizeRequests
                            .requestMatchers(permitMethods).permitAll()
                            .anyRequest().authenticated()
            )
            .userDetailsService(userDetailsService())
            .httpBasic(Customizer.withDefaults())
            // 启用SecurityContext缓存,复用认证结果
            .securityContext(securityContext -> securityContext
                    .securityContextRepository(new DelegatingSecurityContextRepository(
                            new RequestAttributeSecurityContextRepository(),
                            new HttpSessionSecurityContextRepository()
                    )));
    return http.build();
}

3. 校验公开路径匹配规则

确保permitMethods中的路径配置准确,避免公开API或静态资源触发不必要的Basic Auth解析逻辑。可以通过调试确认请求是否被正确匹配到permitAll规则,减少无效的认证流程。

4. 调整容器线程池配置

Spring Boot默认Tomcat线程池在高并发下可能出现线程频繁创建销毁的情况,增加CPU开销。在application.properties中调整线程池参数:

# 调整Tomcat线程池配置
server.tomcat.threads.max=200
server.tomcat.threads.min-spare=50
server.tomcat.accept-count=100

内容的提问来源于stack exchange,提问作者Gog1nA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 01:55:24