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

Spring Boot基于HashiCorp Vault基础认证的性能优化疑问

问题:Spring Boot集成HashiCorp Vault实现Basic认证的性能优化困惑

背景

我正在开发一个集成HashiCorp Vault的Spring Boot应用,希望通过Vault存储用户信息实现Basic Authentication(基础认证)。应用用户量仅5-10个,无需单独数据库存储用户信息。Vault的kv v1引擎中存储了用户名、BCrypt加密密码及用户角色。

初始实现:实时查询Vault认证

最初的实现逻辑是用户登录时,从Vault查询对应用户名的信息,将用户输入的密码与Vault中存储的BCrypt加密密码比对,认证通过后获取用户角色。相关实现如下:

POM依赖

<dependency>
   <groupId>org.springframework.vault</groupId>
   <artifactId>spring-vault-core</artifactId>
   <version>3.0.2</version>
</dependency>

用户POJO类

public class VaultBasicUser {
    private String password;
    private String roles;

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRoles() {
        return roles;
    }

    public void setRoles(String roles) {
        this.roles = roles;
    }
}

自定义认证提供者

@Slf4j
@Component
public class BasicVaultAuthentication implements AuthenticationProvider {

    @Autowired
    private VaultTemplate vaultTemplate;
    
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        
        String name = authentication.getName();
        String password = authentication.getCredentials().toString();
        
        VaultResponseSupport<VaultBasicUser> vaultResponse = vaultTemplate.read("myApp/users/" + name, VaultBasicUser.class);
        
        String vaultSecret = vaultResponse.getData().getPassword();
        
        if (vaultSecret != null) {
            if (BCrypt.checkpw(password, vaultSecret)) {
        
                String vaultRoles = vaultResponse.getData().getRoles();
                        
                List<GrantedAuthority> roles = new ArrayList<>();
                
                String[] stringOfRoles = vaultRoles.split(",");
                for (String singleRole : stringOfRoles) {
                    roles.add(new SimpleGrantedAuthority(singleRole.replaceAll("\s", "")));
                }
                
                UserDetails principal = new User(name, password, roles);
                Authentication auth = new UsernamePasswordAuthenticationToken(principal, password, roles);
                return auth;
            }
            else {
                log.info("Incorrect Credentials (Password)");
                return null;
            }
        }
        else {
            log.info("Incorrect Credentials (User Not found in Vault)");
            return null;
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class
        );
    }
}

该实现可正常运行,但测试发现每次认证耗时约375ms。

优化尝试:预加载用户到内存

为优化性能,我尝试在应用启动时将Vault中的所有用户数据加载到InMemoryUserDetailsManager中,避免每次认证调用Vault API,实现代码如下:

@Bean
public UserDetailsService userDetailsService(PasswordEncoder encoder) {
    
    Collection<UserDetails> allUsers = new ArrayList();

    log.info("Collecting MyApp users from Vault: " + vaultConfig.getUrl());

    // ***** Get All users from Vault HERE ***** 
        VaultEndpoint vaultEndpoint;
        try {
            vaultEndpoint = VaultEndpoint.from(new URI(vaultConfig.getUrl()));
            VaultTemplate vaultTemplate = new VaultTemplate(vaultEndpoint, new TokenAuthentication(vaultConfig.getToken()));
            List<String> vaultUsers = vaultTemplate.list("myApp/users");

            for (String vaultUser : vaultUsers) {
                VaultResponseSupport<VaultBasicUser> vaultResponse = vaultTemplate.read("myApp/users/" + vaultUser, VaultBasicUser.class);
                String password = vaultResponse.getData().getPassword();
                String vaultRoles = vaultResponse.getData().getRoles();
                
                log.info("Adding User: [" + vaultUser + ", " + password + ", " + vaultRoles + "]");
                allUsers.add(User.withUsername(vaultUser).password(password).roles(vaultRoles).build());
            }

        } catch (URISyntaxException ex) {
            log.error("Unable to read in MyApp users from Vault: " + ex.getMessage());
            log.info("Adding some Default Users...");
            allUsers.add(User.withUsername("myapp_admin").password(encoder.encode("adminPassword")).roles("MYADMIN").build());
            allUsers.add(User.withUsername("myapp_poweruser").password(encoder.encode("powerUserPassword")).roles("MYELEVATED").build());
            allUsers.add(User.withUsername("myapp_client").password(encoder.encode("clientPassword")).roles("MYUSER").build());
        }
    } else {
        log.info("Authentication configured for [" + authType.getType() + "] - Not connecting to Vault!");
    }

    return new InMemoryUserDetailsManager(allUsers);
}

但测试发现认证耗时仍约370ms,并未得到优化。我的思路是否存在错误?从内存读取用户信息理应比调用Vault更快,是否存在其他性能瓶颈?

补充说明:已添加NetBeans性能分析截图,分别展示使用自定义认证提供者和InMemoryUserDetailsManager时的性能情况。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 10:13:15