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

密码授权模式下Spring Security OAuth2授权服务器在用户密码错误时重复调用UserDetailsService的问题分析

解决Spring Security OAuth2密码模式下错误密码重复调用UserDetailsService的问题

我之前也碰到过这个一模一样的问题:当使用密码授权模式(password grant type)请求Access Token时,如果用户输入错误密码,授权服务器会反复调用自定义的UserDetailsService,还会多次发起数据库查询,而不是直接返回“密码错误”的提示。从你提供的日志里也能明显看到,多次出现认证失败:密码与存储值不匹配以及重复的数据库连接请求,这就是重复调用loadUserByUsername方法导致的。

问题根源

你已经精准排查到了关键:就是SecurityConfig里被注释掉的那行.and().parentAuthenticationManager(authenticationManagerBean())。当在AuthenticationManagerBuilder中配置父AuthenticationManager时,会触发循环认证流程:OAuth2的TokenEndpoint处理密码模式请求时会调用认证管理器,而如果配置了父管理器,这个认证操作会被重复执行,导致UserDetailsService的loadUserByUsername方法被多次调用——每次调用都会去数据库查询用户信息、角色和权限,造成不必要的资源消耗。

解决方案

保持这行代码的注释状态,不要启用父AuthenticationManager的配置。正确的configure(AuthenticationManagerBuilder auth)配置只需要指定自定义的UserDetailsService和密码编码器即可:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(myUserDetailsService)
            .passwordEncoder(passwordEncoder);
    // 务必保持这行注释,避免循环认证导致重复调用UserDetailsService
    // .and().parentAuthenticationManager(authenticationManagerBean())
}

为什么会重复调用?

当输入错误密码时,第一次认证失败后,如果配置了父AuthenticationManager,认证流程会被再次触发,导致UserDetailsService被重复调用。从你的日志里可以看到,多次出现ProviderManager尝试认证的记录,以及多次从数据源获取JDBC连接——这就是每次调用loadUserByUsername时执行的数据库查询操作。

调整后,当用户输入错误密码时,认证流程只会执行一次,UserDetailsService被调用一次,然后直接返回密码错误的提示,不会再重复触发认证操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 05:14:09