我正在尝试针对我的数据库创建一个简单的登录来验证用户。无论出于何种原因,当预期语句为 true 时,Bcrypt.checkpw 显示 false。我不知所措,为什么会这样。在过去的三天里我尝试了很多事情。例如,对于这些日志,我期望得到正确的匹配,但收到错误的结果。一切都在进行,直到我引入盐/哈希。
查看密码:9999999
对抗哈希:$2a$10$0ATPkyNqcXT8u3RTfoX7BuOzxuTvuNnVH5dgqjVc4agIKHglv7SAC
匹配结果:假
提供的用户名:UNIUSER
提供明文密码:9999999
密码检查失败。存储的密码哈希:
$2a$10$0ATPkyNqcXT8u3RTfoX7BuOzxuTvuNnVH5dgqjVc4agIKHglv7SAC
在我的用户模型中,我有以下相关部分;
public void hashAndSetPassword(String plaintextPassword) {
int saltRounds = 10;
this.passwordHash = BCrypt.hashpw(plaintextPassword, BCrypt.gensalt(saltRounds));
}
public boolean checkPassword(String password) {
boolean isMatch = BCrypt.checkpw(password, passwordHash);
System.out.println("Checking password: " + password);
System.out.println("Against hash: " + passwordHash);
System.out.println("Match result: " + isMatch);
return isMatch;
}
在我的 UserController 中,我有以下内容。
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping("/create")
public ResponseEntity<Map<String, Object>> createUser(@RequestBody User user) {
// Take the plaintext password from the user input
String plaintextPassword = user.getPasswordHash(); // Use getPasswordHash, not getPassword
// Hash the password and set it in the User object
user.hashAndSetPassword(plaintextPassword);
User savedUser = userService.saveUser(user);
Map<String, Object> response = new HashMap<>();
response.put("message", "User created with ID: " + savedUser.getId());
response.put("id", savedUser.getId());
return ResponseEntity.ok(response);
}
private String generateSecureToken() {
SecureRandom random = new SecureRandom();
byte[] bytes = new byte[64];
random.nextBytes(bytes);
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
}
@PostMapping("/login")
public ResponseEntity<Map<String, Object>> login(@RequestBody Map<String, String> credentials,
HttpServletResponse response) {
String username = credentials.get("username");
String password = credentials.get("password");
User user = userService.findByUsername(username);
if (user != null) {
String storedPasswordHash = user.getPasswordHash(); // Get the stored password hash from the database
if (user.checkPassword(password)) { // Compare with hashed password
String sessionToken = generateSecureToken();
user.setSessionToken(sessionToken);
userService.saveUser(user);
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("message", "Login successful");
responseMap.put("username", username);
Cookie cookie = new Cookie("authToken", sessionToken);
cookie.setMaxAge(3600);
cookie.setPath("/"); // Site wide
response.addCookie(cookie);
return ResponseEntity.ok(responseMap);
} else {
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("message", "Login failed");
System.out.println("Provided username: " + username);
System.out.println("Provided plaintext password: " + password);
System.out.println("Password check failed. Stored Password Hash: " + storedPasswordHash);
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(responseMap);
}
} else {
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("message", "User not found");
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(responseMap);
}
}
我在后端使用Java,在前端使用AngularJS。 JBcrypt 版本 0.4,带有 Maven 和 apache。我的数据库的 Oracle 数据库。任何有关此事的见解将不胜感激。 passwordHash 在数据库中存储为 VARCHAR2 (60),因为我之前有 255,但听说 60 可能有帮助。不过什么也没有。谢谢。
无论谁将来遇到这个问题,利用 DTO 来促进该过程都可以解决问题。不太确定考虑面值的确切原因,所有东西都在前/后/DB之间正确携带,但请参阅下面的修复。
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping("/create")
public ResponseEntity<Map<String, Object>> createUser(@RequestBody RegistrationDTO registration) {
User user = new User();
user.setUsername(registration.getUsername());
user.setFirstName(registration.getFirstName());
user.setLastName(registration.getLastName());
user.setTelephone(registration.getTelephone());
user.setAddress(registration.getAddress());
user.setCity(registration.getCity());
user.setPostalCode(registration.getPostalCode());
user.setCountry(registration.getCountry());
user.hashAndSetPassword(registration.getPassword());
User savedUser = userService.saveUser(user);
Map<String, Object> response = new HashMap<>();
response.put("message", "User created with ID: " + savedUser.getId());
response.put("id", savedUser.getId());
return ResponseEntity.ok(response);
}
private String generateSecureToken() {
SecureRandom random = new SecureRandom();
byte[] bytes = new byte[64];
random.nextBytes(bytes);
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
}
@PostMapping("/login")
public ResponseEntity<Map<String, Object>> login(@RequestBody LoginDTO loginDTO, HttpServletResponse response) {
String username = loginDTO.getUsername();
String password = loginDTO.getPassword();
User user = userService.findByUsername(username);
if (user != null) {
if (user.checkPassword(password)) {
String sessionToken = generateSecureToken();
user.setSessionToken(sessionToken);
userService.saveUser(user);
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("message", "Login successful");
responseMap.put("username", username);
Cookie cookie = new Cookie("authToken", sessionToken);
cookie.setMaxAge(3600);
cookie.setPath("/"); // Site wide
response.addCookie(cookie);
return ResponseEntity.ok(responseMap);
} else {
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("message", "Login failed");
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(responseMap);
}
} else {
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("message", "User not found");
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(responseMap);
}
}
}
然后是两个简单的 DTO,例如;
public class RegistrationDTO {
private String username;
private String password;
private String firstName;
private String lastName;
private String telephone;
private String address;
private String city;
private String postalCode;
private String country;
// Getters
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getTelephone() {
return telephone;
}
public String getAddress() {
return address;
}
public String getCity() {
return city;
}
public String getPostalCode() {
return postalCode;
}
public String getCountry() {
return country;
}
// Setters
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public void setAddress(String address) {
this.address = address;
}
public void setCity(String city) {
this.city = city;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public void setCountry(String country) {
this.country = country;
}
}
和登录DTO;
public class LoginDTO {
private String username;
private String password;
// Getters
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
// Setters
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}