refactored a lot

This commit is contained in:
Lorenz Hohermuth 2025-05-15 22:28:17 +02:00
parent 36363716c1
commit a6add75201
6 changed files with 91 additions and 23 deletions

View File

@ -16,6 +16,15 @@ Content-Type: application/json
"passwordConfirmation": "1234" "passwordConfirmation": "1234"
} }
###
POST http://localhost:8080/api/users/login
Content-Type: application/json
{
"email": "violett.weber@bbw.ch",
"password": "1234"
}
### ###
#Get user with id 4 #Get user with id 4
GET http://localhost:8080/api/users/4 GET http://localhost:8080/api/users/4

View File

@ -1,9 +1,6 @@
package ch.bbw.pr.tresorbackend.controller; package ch.bbw.pr.tresorbackend.controller;
import ch.bbw.pr.tresorbackend.model.ConfigProperties; import ch.bbw.pr.tresorbackend.model.*;
import ch.bbw.pr.tresorbackend.model.EmailAdress;
import ch.bbw.pr.tresorbackend.model.RegisterUser;
import ch.bbw.pr.tresorbackend.model.User;
import ch.bbw.pr.tresorbackend.service.PasswordEncryptionService; import ch.bbw.pr.tresorbackend.service.PasswordEncryptionService;
import ch.bbw.pr.tresorbackend.service.UserService; import ch.bbw.pr.tresorbackend.service.UserService;
@ -81,15 +78,13 @@ public class UserController {
System.out.println("UserController.createUser, password validation passed"); System.out.println("UserController.createUser, password validation passed");
//transform registerUser to user //transform registerUser to user
String salt = PasswordEncryptionService.generateSalt();
User user = new User( User user = new User(
null, null,
registerUser.getFirstName(), registerUser.getFirstName(),
registerUser.getLastName(), registerUser.getLastName(),
registerUser.getEmail(), registerUser.getEmail(),
passwordService.hashPassword(registerUser.getPassword(), salt), passwordService.hashPassword(registerUser.getPassword())
salt
); );
User savedUser = userService.createUser(user); User savedUser = userService.createUser(user);
@ -110,6 +105,34 @@ public class UserController {
return new ResponseEntity<>(user, HttpStatus.OK); return new ResponseEntity<>(user, HttpStatus.OK);
} }
@CrossOrigin(origins = "${CROSS_ORIGIN}")
@PostMapping("/login")
public ResponseEntity<String> login(@Valid @RequestBody LoginRequest loginRequest, BindingResult bindingResult) {
//input validation
if (bindingResult.hasErrors()) {
List<String> errors = bindingResult.getFieldErrors().stream()
.map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage())
.collect(Collectors.toList());
System.out.println("UserController.createUser " + errors);
JsonArray arr = new JsonArray();
errors.forEach(arr::add);
JsonObject obj = new JsonObject();
obj.add("message", arr);
String json = new Gson().toJson(obj);
System.out.println("UserController.createUser, validation fails: " + json);
return ResponseEntity.badRequest().body(json);
}
User user = userService.findByEmail(loginRequest.getEmail());
if (user != null && passwordService.verifyPassword(user, loginRequest.getPassword())) {
return ResponseEntity.status(200).body("User logged in");
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
// Build Get All Users REST API // Build Get All Users REST API
// http://localhost:8080/api/users // http://localhost:8080/api/users
@CrossOrigin(origins = "${CROSS_ORIGIN}") @CrossOrigin(origins = "${CROSS_ORIGIN}")

View File

@ -0,0 +1,21 @@
package ch.bbw.pr.tresorbackend.model;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class LoginRequest {
@NotEmpty(message = "Email cannot be empty")
@Email(message = "Invalid email format")
private String email;
@NotEmpty(message = "Password cannot be empty")
private String password;
}

View File

@ -32,7 +32,4 @@ public class User {
@Column(nullable = false) @Column(nullable = false)
private String password; private String password;
@Column(nullable = false)
private String salt;
} }

View File

@ -1,11 +1,14 @@
package ch.bbw.pr.tresorbackend.service; package ch.bbw.pr.tresorbackend.service;
import ch.bbw.pr.tresorbackend.model.User;
import lombok.Value; import lombok.Value;
import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Objects;
/** /**
* PasswordEncryptionService * PasswordEncryptionService
@ -15,23 +18,38 @@ import java.security.SecureRandom;
@Service @Service
public class PasswordEncryptionService { public class PasswordEncryptionService {
@Autowired
private PepperService pepperService;
private final BCryptPasswordEncoder encoder;
public PasswordEncryptionService() { public PasswordEncryptionService() {
//todo anpassen! this.encoder = new BCryptPasswordEncoder();
} }
public static String generateSalt() { public String hashPassword(String password) {
byte[] salt = new byte[5]; String pepper = pepperService.getPepper();
new SecureRandom().nextBytes(salt);
return Hex.toHexString(salt); if (pepper == null || pepper.isEmpty()) {
throw new IllegalStateException("Pepper is missing or empty");
}
// Combine pepper and password, let BCrypt handle salting internally
String connectedPassword = pepper + password;
return encoder.encode(connectedPassword);
} }
public String hashPassword(String password, String salt) { public boolean verifyPassword(User user, String password) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); String pepper = pepperService.getPepper();
String pepper = new PepperService().getPepper();
return encoder.encode(pepper + password ); if (pepper == null || pepper.isEmpty()) {
throw new IllegalStateException("Pepper is missing or empty");
}
// Reconstruct the original password with pepper
String connectedPassword = pepper + password;
// Directly compare the stored hash with the user input
return encoder.matches(connectedPassword, user.getPassword());
} }
} }
record PasswordBean(String hashedPassword, String Salt) {
}

View File

@ -33,7 +33,7 @@ public class UserServiceImpl implements UserService {
@Override @Override
public User findByEmail(String email) { public User findByEmail(String email) {
Optional<User> optionalUser = userRepository.findByEmail(email); Optional<User> optionalUser = userRepository.findByEmail(email);
return optionalUser.get(); return optionalUser.orElse(null);
} }
@Override @Override