Spring中CrudRepository findOne返回表单值,登录验证异常求助
登录功能问题排查与修复
问题核心原因
- Repository/Service实现错误:若
UsuarioService.findOne未正确调用CrudRepository的查询方法,而是直接返回表单绑定的Usuario对象,会导致返回数据与数据库不符。 - 字符串比较逻辑错误:使用
==比较密码是引用地址对比,而非内容对比,会导致密码验证失效。 - 重复查询的低效与风险:原代码多次调用
findOne,既浪费资源又可能因上下文缓存引发意外结果。
修复步骤
1. 确保Repository层正确实现
检查UsuarioRepository是否正确继承CrudRepository,且未错误重写查询方法:
import org.springframework.data.repository.CrudRepository; public interface UsuarioRepository extends CrudRepository<Usuario, String> { // 无需额外定义,CrudRepository自带主键查询能力 }
2. 修正Service层的findOne方法
Spring Data JPA 2.x及以上版本中,CrudRepository.findOne(ID)已替换为findById(ID)(返回Optional),Service层需正确处理:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UsuarioServiceImpl implements UsuarioService { @Autowired private UsuarioRepository usuarioRepository; @Override public Usuario findOne(String username) { // 查询数据库,无匹配则返回null return usuarioRepository.findById(username).orElse(null); } }
3. 重构Controller逻辑
- 仅查询一次数据库用户并复用结果
- 使用
equals()进行密码内容比较 - 验证通过后传入数据库用户对象而非表单对象
import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class AccesoController { @Autowired private UsuarioService usuarioService; @RequestMapping(value = "/acceso", method=RequestMethod.POST) public String acceder(Model model, @Validated Usuario formUsuario, BindingResult result) { if (result.hasErrors()) { return "acceso"; } // 单次查询数据库中的用户 Usuario dbUsuario = usuarioService.findOne(formUsuario.getUsuario()); // 打印对比数据,排查对象来源 System.out.println("数据库用户:" + dbUsuario); System.out.println("表单提交用户:" + formUsuario); if (dbUsuario == null) { model.addAttribute("error","Usuario no existente. Inténtelo de nuevo"); return "acceso"; } // 用equals比较密码内容,避免引用地址对比 if (dbUsuario.getContrasena().equals(formUsuario.getContrasena())) { model.addAttribute("usuario", dbUsuario); return "index"; } else { model.addAttribute("errContra","Contraseña incorrecta, inténtelo de nuevo"); return "acceso"; } } }
4. 关键安全优化:密码加密
禁止存储明文密码,使用BCrypt算法加密存储:
// 注册用户时加密密码 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; public void saveUsuario(Usuario usuario) { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); usuario.setContrasena(encoder.encode(usuario.getContrasena())); usuarioRepository.save(usuario); } // 登录时验证密码 if (encoder.matches(formUsuario.getContrasena(), dbUsuario.getContrasena())) { // 密码验证通过 }
内容的提问来源于stack exchange,提问作者Loki
相关产品推荐
相关产品推荐

