英文:
Spring Security login failed
问题
使用定制数据源和Spring Security密码编码器,但登录失败。
Spring Boot版本为2.7.0。
我首先注册了一个名为"132456"的用户,密码为"123456",然后尝试登录,但失败了。
然后我创建了一个测试类:打印true。
    @Test
    public void selectTest() {
        UserDetails userDetails = userInfoService.loadUserByUsername("123456");
        System.out.println(userDetails);
        boolean matches = passwordEncoder.matches("123456", userDetails.getPassword());
        System.out.println(matches);
    }
Spring Security配置
@EnableWebSecurity
@Configuration
@Slf4j
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration {
    @Autowired
    UserInfoService userInfoService;
    @Autowired
    Gson gson;
    @Autowired
    JwtTokenFilter jwtTokenFilter;
    @Autowired
    PasswordEncoder passwordEncoder;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        .... 登录URL已经通过
        http.formLogin().loginProcessingUrl("/api/login").permitAll()
                .successHandler((request, response, authentication) -> {
                    this.sendMessage(response, authentication);
                })
                .failureHandler((request, response, exception) ->
                        jwtTokenFilter.sendError(response, HttpServletResponse.SC_UNAUTHORIZED, "用户名或密码错误"));
        http.logout().invalidateHttpSession(true).clearAuthentication(false);
        http.rememberMe().disable();
        http.csrf().disable();
        return http.build();
    }
    
    @Bean
    DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userInfoService);
        authProvider.setPasswordEncoder(passwordEncoder);
        return authProvider;
    }
}
userServiceImpl
// 使用mybatisplus框架
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
    @Autowired
    PasswordEncoder passwordEncoder;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getUsername, username);
        return getOne(queryWrapper);
    }
    @Override
    public boolean create(UserInfoDTO userInfoDTO) {
        userInfoDTO.setPassword(passwordEncoder.encode(userInfoDTO.getPassword()));
        return save(BeanUtil.copyProperties(userInfoDTO, UserInfo.class));
    }
}
登录成功后,返回令牌。
英文:
Use customized datasource and Spring Security password encoder, but login failed.
Spring Boot version 2.7.0
I first register a user named "132456", passsword "123456", then login, but failed;
Then I create a test class: print true
    @Test
    public void selectTest() {
        UserDetails userDetails = userInfoService.loadUserByUsername("123456");
        System.out.println(userDetails);
        boolean matches = passwordEncoder.matches("123456", userDetails.getPassword());
        System.out.println(matches);
    }
Spring Security config
@EnableWebSecurity
@Configuration
@Slf4j
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration {
    @Autowired
    UserInfoService userInfoService;
    @Autowired
    Gson gson;
    @Autowired
    JwtTokenFilter jwtTokenFilter;
    @Autowired
    PasswordEncoder passwordEncoder;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        .... login url has pass
        http.formLogin().loginProcessingUrl("/api/login").permitAll()
                .successHandler((request, response, authentication) -> {
                    this.sendMessage(response, authentication);
                })
                .failureHandler((request, response, exception) ->
                        jwtTokenFilter.sendError(response, HttpServletResponse.SC_UNAUTHORIZED, "username or password error"));
        http.logout().invalidateHttpSession(true).clearAuthentication(false);
        http.rememberMe().disable();
        http.csrf().disable();
        return http.build();
    }
    
    @Bean
    DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userInfoService);
        authProvider.setPasswordEncoder(passwordEncoder);
        return authProvider;
    }
}
userServiceImpl
// use mybatisplus framework
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
    @Autowired
    PasswordEncoder passwordEncoder;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getUsername, username);
        return getOne(queryWrapper);
    }
    @Override
    public boolean create(UserInfoDTO userInfoDTO) {
        userInfoDTO.setPassword(passwordEncoder.encode(userInfoDTO.getPassword()));
        return save(BeanUtil.copyProperties(userInfoDTO, UserInfo.class));
    }
}
login success, then return token.
答案1
得分: 1
Omg,我忘了覆盖接口UserDetails内部方法:isEnabled(),哈哈哈。花了两个小时找到这个错误。
/**
 * 指示用户是否已启用或禁用。禁用的用户无法进行身份验证。
 * @return 如果用户已启用,则返回<code>true</code>,否则返回<code>false</code>
 */
boolean isEnabled();
英文:
Omg, I forgot to override the interface UserDetails inner method: isEnabled(), Hahahah. Spent two hours finding this bug.
/**
 * Indicates whether the user is enabled or disabled. A disabled user cannot be
 * authenticated.
 * @return <code>true</code> if the user is enabled, <code>false</code> otherwise
 */
boolean isEnabled();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论