【问题标题】:How to compare text password to password that is hashed using spring data jpa?如何将文本密码与使用 spring data jpa 散列的密码进行比较?
【发布时间】:2020-09-21 02:26:13
【问题描述】:

我的密码在保存时在数据库中进行了哈希处理。但是我现在正在实现登录模块,并且无法在 spring [boot] data jpa 中比较两个密码。这是尝试将我输入的文本密码与在数据库中散列的密码进行比较,这显然失败了。

我知道这个问题已经回答here using java 用于一般情况,但不适用于弹簧靴。

我需要在这段代码中操作逻辑

@Override
public boolean getLoggedinUser(User user) {

    String uname = user.getUsername();
    String email = user.getEmail();
    String password = user.getPassword();

    System.out.println("sanity check username----- " + uname  + 
            " password ------- " + password);

    if ((userRepo.findByUsername(uname) != null && userRepo.findByPassword(password) != null)
            || (userRepo.findByPassword(password) != null && userRepo.findByEmail(email) != null)) {

        return true;
    }
    else return false;
}

现在,如何比较它们?任何解决方案表示赞赏。

【问题讨论】:

  • 我看到的唯一解决方案是将散列/编码机制移出数据库并将其应用于给定密码。这样您就可以比较哈希/编码密码。
  • 你考虑过使用 BCrypt 吗? stackoverflow.com/questions/26905721/…
  • @Romano 是的,我正在使用 Bcrypt 。 BCryptPasswordEncoder bcryptEncoder = new BCryptPasswordEncoder(); boolean isMatched = bcryptEncoder.matches(password, userRepo.findByPassword(password)); System.out.println("匹配 ???? ----------------" + isMatched);返回 false 为什么?我输入的密码正确。
  • 您是否 100% 确定也使用 BCrypt 生成了数据库密码?如果是,您是否使用盐?
  • @Romano,是的,它正在生成 100% ,但我无法比较它。

标签: java spring-boot spring-data-jpa


【解决方案1】:

我将其用作开箱即用的解决方案,它全部由 spring 管理

@RestController
@RequestMapping("/api")
public class UserJWTController {



private final AuthenticationManagerBuilder authenticationManagerBuilder;

public UserJWTController( AuthenticationManagerBuilder authenticationManagerBuilder, 
....other dependancies) {
    //other dependancies
    this.authenticationManagerBuilder = authenticationManagerBuilder;
}

@PostMapping("/authenticate")
public ResponseEntity<JWTToken> authorize(@Valid @RequestBody LoginVM loginVM) {

    String authenticateWith = loginVM.getEmail()==null? 
  loginVM.getUsername():loginVM.getEmail();
    if(authenticateWith==null||authenticateWith.trim().isEmpty()) {
        return ResponseEntity.badRequest().build();
    }

    UsernamePasswordAuthenticationToken authenticationToken =
        new UsernamePasswordAuthenticationToken(authenticateWith.toLowerCase(), 
   loginVM.getPassword());

    Authentication authentication = 
  authenticationManagerBuilder.getObject().authenticate(authenticationToken);
    SecurityContextHolder.getContext().setAuthentication(authentication);

【讨论】:

  • 导入是 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;导入 org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;导入 org.springframework.security.core.Authentication;
【解决方案2】:

我通过这种方式解决了上述问题。但是,如果我可以通过其他任何方式优化解决方案,请告诉我。

@Override
public boolean getLoggedinUser(User user) {
    String uname = user.getUsername();
    String email = user.getEmail();
    String password = user.getPassword();

    BCryptPasswordEncoder bcryptEncoder = new BCryptPasswordEncoder();

    User userWithUsername = userRepo.findByUsername(uname);//as username is unique
    User userWithEmail = userRepo.findByEmail(email); //unique email

    String hashedPassword = "";

     if(userWithUsername !=null) {
        hashedPassword = userWithUsername.getPassword();
      System.out.println("------------" + userWithUsername + " _------------- " + hashedPassword);
     }

     else if(userWithEmail !=null) {
            hashedPassword = userWithEmail.getPassword();
          System.out.println("------------" + userWithUsername + " _------------- " + hashedPassword);
     }

    boolean isPasswordMatched = bcryptEncoder.matches(password, hashedPassword);

if(((userWithUsername ==null && userWithEmail != null ) && userWithEmail.isEnabled() == false) || ((userWithEmail ==null && userWithUsername !=null) && userWithUsername.isEnabled() == false)) {   
        return false;
    }

    if ((userRepo.findByUsername(uname) !=null && isPasswordMatched) || (userRepo.findByEmail(email) !=null && isPasswordMatched)) {
        return true;
    }
   return false;
}

【讨论】:

  • 看起来您正在使用 Spring Security。为什么?
  • @M.Deinum,是的,但我也想在用户注册时加密用户的密码,然后实现该用户是否存在,所以我必须比较用户输入的密码到加密并存储在数据库中的密码。这不是一个好方法吗?我对 Spring Security 有点陌生。
  • 不,不是。另外,您为什么需要比较密码以查看某人是否已经存在?您可以为 2 个用户使用相同的用户名,但让他们的密码不同吗?!如果您想检查是否存在,只需让 Spring Data 处理它并为其编写一个方法 existsByUsernameOrEmail(String username, String email) 将返回一个 boolean 指示是否找到记录。
  • @M.Deinum,是的,你是对的,但我正在尝试的是允许用户是否允许进入站点?仅当用户具有用户名和密码或电子邮件和密码行进时才允许。比如,如果有匹配的凭据,Facebook 如何允许我们登录。如果我错了,请纠正我。
  • 这是您现在绕过的 Spring Security 的任务。如果您开始解决它,为什么要使用安全框架?
猜你喜欢
  • 2016-09-19
  • 1970-01-01
  • 2020-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-27
  • 2018-09-17
  • 2015-01-29
相关资源
最近更新 更多