Spring登录异常排查:loadUserByUsername方法未被调用
问题现象
刚接触Spring框架,开发简易登录应用,代码可正常编译,但输入数据库中存在的正确账号密码时始终无法登录。怀疑loadUserByUsername方法未被调用(无报错、无日志输出),且在控制器中添加日志后,获取到的邮箱和密码均为null。
核心问题分析
Spring Security表单登录默认会从请求中读取名为username和password的字段值,但你的前端登录表单中,邮箱输入框的name属性是emailAddress,不符合Security的默认参数名要求。这导致Security无法正确获取用户名参数,进而不会触发loadUserByUsername方法,最终登录失败。
解决方案
方案一:修改前端表单字段名
将登录表单中邮箱输入框的name属性改为username,匹配Security默认规则:
<input type="text" id="emailAddress" name="username" class="form-control" placeholder="Enter email address" />
方案二:配置Spring Security自定义字段名
如果不想修改前端代码,可在SecurityConfig的formLogin配置中指定自定义参数名:
.formLogin(form -> form .loginPage("/login") .loginProcessingUrl("/login") .defaultSuccessUrl("/") .usernameParameter("emailAddress") // 指定用户名参数为emailAddress .passwordParameter("password") // 密码参数与默认一致,可省略,此处显式声明更清晰 .permitAll())
额外需要修正的问题
主键类型不匹配:User类的
userKey是int类型,但UserRepository继承JpaRepository时用了Long作为主键类型,会导致JPA操作异常,需统一类型:public interface UserRepository extends JpaRepository<User, Integer> { Optional<User> findByEmailAddress(String email); }密码加密验证:确保数据库中存储的密码是通过
BCryptPasswordEncoder加密后的字符串,而非明文。若之前是明文存储,需先加密再存入数据库,否则Security的密码匹配逻辑会失败。语法错误修正:原SecurityConfig中
authorizeHttpRequests存在语法笔误,需将authorize -改为authorize ->,否则会编译失败。
修正后的核心代码示例
修正后的SecurityConfig.java
@Configuration public class SecurityConfig { private final UserDetail userDetail; @Autowired public SecurityConfig(UserDetail userDetail) { this.userDetail = userDetail; } @Bean public static PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated()) .formLogin(form -> form .loginPage("/login") .loginProcessingUrl("/login") .defaultSuccessUrl("/") .usernameParameter("emailAddress") .permitAll()) .logout(logout -> logout .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .permitAll()); http.userDetailsService(userDetail); return http.build(); } }
内容的提问来源于stack exchange,提问作者Hubert Kiszka

