在 Spring Boot - JPA 中有效匹配密码

Match password efficiently in Spring Boot - JPA

我有 User class 这样的 :

@Data
@Entity
public class User {
@Id @GeneratedValue Long userID;
String eMail;
String passwordHash;
}

我有这样的数据:

[{"userID":1,"passwordHash":"asdasd","email":"admin@admin.com"},
{"userID":2,"passwordHash":"12345","email":"admin1asdasd@admin.com"}]

我有两种方法,一种是获得单个用户:

// Single item

@GetMapping("/user/{id}")
User one(@PathVariable Long id) {

    return repository.findById(id)
            .orElseThrow(() -> new UserNotFoundException(id));
}

检索所有用户的其他方法:

// Aggregate root

@GetMapping("/user")
List<User> all() {
    return repository.findAll();
}

现在如何匹配密码?什么是有效的方法?

您可能需要考虑this kind of an aproach:一般来说,您应该将散列密码保存在数据库中并使用散列值检查密码。 Bcrypt 是一个很好的散列选项,它可以很容易地与 Spring.

集成

如上面 link 中所述,您可以定义密码编码器服务:

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

你可以这样使用它:

@Autowired
private PasswordEncoder passwordEncoder;

//...
User user = new User();
user.setFirstName(accountDto.getFirstName());
user.setLastName(accountDto.getLastName());

user.setPassword(passwordEncoder.encode(accountDto.getPassword()));

user.setEmail(accountDto.getEmail());
user.setRole(new Role(Integer.valueOf(1), user));
repository.save(user);

其中 accountDto 包含明文密码。

现在您可以公开比较散列值的专用登录方法,大致如下:

void login(String username, char[] password) throws Exception {
    User user = userRepository.findByUsername(username);
    if (user != null) {
        String encodedPassword = user.getPassword();
        if(passwordEncoder.matches(String.valueOf(password), encodedPassword)) {
            return;
        }
    }
    throw new Exception("User cannot be authenticated");
}