Spring Boot Security中Authentication Manager未接收username参数问题
现象
执行authManager.authenticate()时,虽然构造UsernamePasswordAuthenticationToken时传入了有效username(打印结果显示Principal=test),但Hibernate执行的SQL查询中u1_0.username=?的参数丢失,导致认证失败。
相关代码与输出
认证方法代码
public AuthenticationResponse authenticate(AuthenticationRequest request){ authManager.authenticate( new UsernamePasswordAuthenticationToken( request.getUsername(), request.getPassword() ) ); return null; // returns other stuff, irrelevant }
控制台SQL输出
Hibernate: select u1_0.id,u1_0.email,u1_0.password,u1_0.role,u1_0.username from user u1_0 where u1_0.username=?
Token打印结果
UsernamePasswordAuthenticationToken [Principal=test, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]]
排查方向
检查UserDetailsService实现
确认自定义UserDetailsService的loadUserByUsername方法是否正确使用传入的username参数查询数据库。比如JPA方法名是否为findByUsername,或者@Query注解中是否正确绑定参数(如:username对应方法参数),避免出现参数绑定错误。验证AuthenticationRequest的getUsername()方法
在调用authManager.authenticate()前打印request.getUsername()的值,确认该方法是否正确返回预期的username。排查是否存在类字段名与getter不匹配(如字段为userName但getter为getUsername())、JSON反序列化字段不匹配等问题。检查AuthenticationManager配置
确认AuthenticationManager是否配置了自定义AuthenticationProvider,且该Provider的authenticate方法是否正确从Authentication对象中获取username(通过authentication.getName())。避免因错误获取字段导致username丢失。开启Hibernate参数日志
添加日志配置logging.level.org.hibernate.type.descriptor.sql=TRACE,查看SQL查询实际绑定的参数值。如果参数为空,问题出在UserDetailsService获取username的环节;如果参数有效但无查询结果,需检查数据库数据是否匹配(如大小写敏感)。排查过滤器/拦截器影响
确认项目中是否存在自定义过滤器或拦截器,在认证流程前修改了请求的username参数,导致最终传入UsernamePasswordAuthenticationToken的值被篡改。
内容的提问来源于stack exchange,提问作者LautaroColella

