added hashing to registering new user
This commit is contained in:
		
							parent
							
								
									3408f01598
								
							
						
					
					
						commit
						36363716c1
					
				|  | @ -66,6 +66,28 @@ | ||||||
|             <artifactId>jasypt-spring-boot-starter</artifactId> |             <artifactId>jasypt-spring-boot-starter</artifactId> | ||||||
|             <version>3.0.5</version> |             <version>3.0.5</version> | ||||||
|         </dependency> |         </dependency> | ||||||
|  | 
 | ||||||
|  |         <!-- Bouncy Castle for secure hashing and random salt generation --> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.bouncycastle</groupId> | ||||||
|  |             <artifactId>bcprov-jdk18on</artifactId> | ||||||
|  |             <version>1.76</version> | ||||||
|  |         </dependency> | ||||||
|  | 
 | ||||||
|  |         <!-- Spring Security for password encoding (bcrypt) --> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.security</groupId> | ||||||
|  |             <artifactId>spring-security-crypto</artifactId> | ||||||
|  |             <version>6.1.2</version> | ||||||
|  |         </dependency> | ||||||
|  | 
 | ||||||
|  |         <!-- Apache Commons Codec for encoding (like Base64) --> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>commons-codec</groupId> | ||||||
|  |             <artifactId>commons-codec</artifactId> | ||||||
|  |             <version>1.16.0</version> | ||||||
|  |         </dependency> | ||||||
|  | 
 | ||||||
|     </dependencies> |     </dependencies> | ||||||
| 
 | 
 | ||||||
|     <build> |     <build> | ||||||
|  |  | ||||||
|  | @ -32,150 +32,153 @@ import java.util.stream.Collectors; | ||||||
| @RequestMapping("api/users") | @RequestMapping("api/users") | ||||||
| public class UserController { | public class UserController { | ||||||
| 
 | 
 | ||||||
|    private UserService userService; |     private UserService userService; | ||||||
|    private PasswordEncryptionService passwordService; |     private PasswordEncryptionService passwordService; | ||||||
|    private final ConfigProperties configProperties; |     private final ConfigProperties configProperties; | ||||||
|    private static final Logger logger = LoggerFactory.getLogger(UserController.class); |     private static final Logger logger = LoggerFactory.getLogger(UserController.class); | ||||||
| 
 | 
 | ||||||
|    @Autowired |     @Autowired | ||||||
|    public UserController(ConfigProperties configProperties, UserService userService, |     public UserController(ConfigProperties configProperties, UserService userService, | ||||||
|                          PasswordEncryptionService passwordService) { |                           PasswordEncryptionService passwordService) { | ||||||
|       this.configProperties = configProperties; |         this.configProperties = configProperties; | ||||||
|       System.out.println("UserController.UserController: cross origin: " + configProperties.getOrigin()); |         System.out.println("UserController.UserController: cross origin: " + configProperties.getOrigin()); | ||||||
|       // Logging in the constructor |         // Logging in the constructor | ||||||
|       logger.info("UserController initialized: " + configProperties.getOrigin()); |         logger.info("UserController initialized: " + configProperties.getOrigin()); | ||||||
|       logger.debug("UserController.UserController: Cross Origin Config: {}", configProperties.getOrigin()); |         logger.debug("UserController.UserController: Cross Origin Config: {}", configProperties.getOrigin()); | ||||||
|       this.userService = userService; |         this.userService = userService; | ||||||
|       this.passwordService = passwordService; |         this.passwordService = passwordService; | ||||||
|    } |     } | ||||||
| 
 | 
 | ||||||
|    // build create User REST API |     // build create User REST API | ||||||
|    @CrossOrigin(origins = "${CROSS_ORIGIN}") |     @CrossOrigin(origins = "${CROSS_ORIGIN}") | ||||||
|    @PostMapping |     @PostMapping | ||||||
|    public ResponseEntity<String> createUser(@Valid @RequestBody RegisterUser registerUser, BindingResult bindingResult) { |     public ResponseEntity<String> createUser(@Valid @RequestBody RegisterUser registerUser, BindingResult bindingResult) { | ||||||
|       //captcha |         //captcha | ||||||
|       //todo ergänzen |         //todo ergänzen | ||||||
| 
 | 
 | ||||||
|       System.out.println("UserController.createUser: captcha passed."); |         System.out.println("UserController.createUser: captcha passed."); | ||||||
| 
 | 
 | ||||||
|       //input validation |         //input validation | ||||||
|       if (bindingResult.hasErrors()) { |         if (bindingResult.hasErrors()) { | ||||||
|          List<String> errors = bindingResult.getFieldErrors().stream() |             List<String> errors = bindingResult.getFieldErrors().stream() | ||||||
|                .map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage()) |                     .map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage()) | ||||||
|                .collect(Collectors.toList()); |                     .collect(Collectors.toList()); | ||||||
|          System.out.println("UserController.createUser " + errors); |             System.out.println("UserController.createUser " + errors); | ||||||
| 
 | 
 | ||||||
|          JsonArray arr = new JsonArray(); |             JsonArray arr = new JsonArray(); | ||||||
|          errors.forEach(arr::add); |             errors.forEach(arr::add); | ||||||
|          JsonObject obj = new JsonObject(); |             JsonObject obj = new JsonObject(); | ||||||
|          obj.add("message", arr); |             obj.add("message", arr); | ||||||
|          String json = new Gson().toJson(obj); |             String json = new Gson().toJson(obj); | ||||||
| 
 | 
 | ||||||
|          System.out.println("UserController.createUser, validation fails: " + json); |             System.out.println("UserController.createUser, validation fails: " + json); | ||||||
|          return ResponseEntity.badRequest().body(json); |             return ResponseEntity.badRequest().body(json); | ||||||
|       } |         } | ||||||
|       System.out.println("UserController.createUser: input validation passed"); |         System.out.println("UserController.createUser: input validation passed"); | ||||||
| 
 | 
 | ||||||
|       //password validation |         //password validation | ||||||
|       //todo ergänzen |         //todo ergänzen | ||||||
|       System.out.println("UserController.createUser, password validation passed"); |         System.out.println("UserController.createUser, password validation passed"); | ||||||
| 
 | 
 | ||||||
|       //transform registerUser to user |         //transform registerUser to user | ||||||
|       User user = new User( |         String salt = PasswordEncryptionService.generateSalt(); | ||||||
|             null, |  | ||||||
|             registerUser.getFirstName(), |  | ||||||
|             registerUser.getLastName(), |  | ||||||
|             registerUser.getEmail(), |  | ||||||
|             passwordService.hashPassword(registerUser.getPassword()) |  | ||||||
|             ); |  | ||||||
| 
 | 
 | ||||||
|       User savedUser = userService.createUser(user); |         User user = new User( | ||||||
|       System.out.println("UserController.createUser, user saved in db"); |                 null, | ||||||
|       JsonObject obj = new JsonObject(); |                 registerUser.getFirstName(), | ||||||
|       obj.addProperty("answer", "User Saved"); |                 registerUser.getLastName(), | ||||||
|       String json = new Gson().toJson(obj); |                 registerUser.getEmail(), | ||||||
|       System.out.println("UserController.createUser " + json); |                 passwordService.hashPassword(registerUser.getPassword(), salt), | ||||||
|       return ResponseEntity.accepted().body(json); |                 salt | ||||||
|    } |         ); | ||||||
| 
 | 
 | ||||||
|    // build get user by id REST API |         User savedUser = userService.createUser(user); | ||||||
|    // http://localhost:8080/api/users/1 |         System.out.println("UserController.createUser, user saved in db"); | ||||||
|    @CrossOrigin(origins = "${CROSS_ORIGIN}") |         JsonObject obj = new JsonObject(); | ||||||
|    @GetMapping("{id}") |         obj.addProperty("answer", "User Saved"); | ||||||
|    public ResponseEntity<User> getUserById(@PathVariable("id") Long userId) { |         String json = new Gson().toJson(obj); | ||||||
|       User user = userService.getUserById(userId); |         System.out.println("UserController.createUser " + json); | ||||||
|       return new ResponseEntity<>(user, HttpStatus.OK); |         return ResponseEntity.accepted().body(json); | ||||||
|    } |     } | ||||||
| 
 | 
 | ||||||
|    // Build Get All Users REST API |     // build get user by id REST API | ||||||
|    // http://localhost:8080/api/users |     // http://localhost:8080/api/users/1 | ||||||
|    @CrossOrigin(origins = "${CROSS_ORIGIN}") |     @CrossOrigin(origins = "${CROSS_ORIGIN}") | ||||||
|    @GetMapping |     @GetMapping("{id}") | ||||||
|    public ResponseEntity<List<User>> getAllUsers() { |     public ResponseEntity<User> getUserById(@PathVariable("id") Long userId) { | ||||||
|       List<User> users = userService.getAllUsers(); |         User user = userService.getUserById(userId); | ||||||
|       return new ResponseEntity<>(users, HttpStatus.OK); |         return new ResponseEntity<>(user, HttpStatus.OK); | ||||||
|    } |     } | ||||||
| 
 | 
 | ||||||
|    // Build Update User REST API |     // Build Get All Users REST API | ||||||
|    // http://localhost:8080/api/users/1 |     // http://localhost:8080/api/users | ||||||
|    @CrossOrigin(origins = "${CROSS_ORIGIN}") |     @CrossOrigin(origins = "${CROSS_ORIGIN}") | ||||||
|    @PutMapping("{id}") |     @GetMapping | ||||||
|    public ResponseEntity<User> updateUser(@PathVariable("id") Long userId, |     public ResponseEntity<List<User>> getAllUsers() { | ||||||
|                                           @RequestBody User user) { |         List<User> users = userService.getAllUsers(); | ||||||
|       user.setId(userId); |         return new ResponseEntity<>(users, HttpStatus.OK); | ||||||
|       User updatedUser = userService.updateUser(user); |     } | ||||||
|       return new ResponseEntity<>(updatedUser, HttpStatus.OK); |  | ||||||
|    } |  | ||||||
| 
 | 
 | ||||||
|    // Build Delete User REST API |     // Build Update User REST API | ||||||
|    @CrossOrigin(origins = "${CROSS_ORIGIN}") |     // http://localhost:8080/api/users/1 | ||||||
|    @DeleteMapping("{id}") |     @CrossOrigin(origins = "${CROSS_ORIGIN}") | ||||||
|    public ResponseEntity<String> deleteUser(@PathVariable("id") Long userId) { |     @PutMapping("{id}") | ||||||
|       userService.deleteUser(userId); |     public ResponseEntity<User> updateUser(@PathVariable("id") Long userId, | ||||||
|       return new ResponseEntity<>("User successfully deleted!", HttpStatus.OK); |                                            @RequestBody User user) { | ||||||
|    } |         user.setId(userId); | ||||||
|  |         User updatedUser = userService.updateUser(user); | ||||||
|  |         return new ResponseEntity<>(updatedUser, HttpStatus.OK); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Build Delete User REST API | ||||||
|  |     @CrossOrigin(origins = "${CROSS_ORIGIN}") | ||||||
|  |     @DeleteMapping("{id}") | ||||||
|  |     public ResponseEntity<String> deleteUser(@PathVariable("id") Long userId) { | ||||||
|  |         userService.deleteUser(userId); | ||||||
|  |         return new ResponseEntity<>("User successfully deleted!", HttpStatus.OK); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|    // get user id by email |     // get user id by email | ||||||
|    @CrossOrigin(origins = "${CROSS_ORIGIN}") |     @CrossOrigin(origins = "${CROSS_ORIGIN}") | ||||||
|    @PostMapping("/byemail") |     @PostMapping("/byemail") | ||||||
|    public ResponseEntity<String> getUserIdByEmail(@RequestBody EmailAdress email, BindingResult bindingResult) { |     public ResponseEntity<String> getUserIdByEmail(@RequestBody EmailAdress email, BindingResult bindingResult) { | ||||||
|       System.out.println("UserController.getUserIdByEmail: " + email); |         System.out.println("UserController.getUserIdByEmail: " + email); | ||||||
|       //input validation |         //input validation | ||||||
|       if (bindingResult.hasErrors()) { |         if (bindingResult.hasErrors()) { | ||||||
|          List<String> errors = bindingResult.getFieldErrors().stream() |             List<String> errors = bindingResult.getFieldErrors().stream() | ||||||
|                .map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage()) |                     .map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage()) | ||||||
|                .collect(Collectors.toList()); |                     .collect(Collectors.toList()); | ||||||
|          System.out.println("UserController.createUser " + errors); |             System.out.println("UserController.createUser " + errors); | ||||||
| 
 | 
 | ||||||
|          JsonArray arr = new JsonArray(); |             JsonArray arr = new JsonArray(); | ||||||
|          errors.forEach(arr::add); |             errors.forEach(arr::add); | ||||||
|          JsonObject obj = new JsonObject(); |             JsonObject obj = new JsonObject(); | ||||||
|          obj.add("message", arr); |             obj.add("message", arr); | ||||||
|          String json = new Gson().toJson(obj); |             String json = new Gson().toJson(obj); | ||||||
| 
 | 
 | ||||||
|          System.out.println("UserController.createUser, validation fails: " + json); |             System.out.println("UserController.createUser, validation fails: " + json); | ||||||
|          return ResponseEntity.badRequest().body(json); |             return ResponseEntity.badRequest().body(json); | ||||||
|       } |         } | ||||||
| 
 | 
 | ||||||
|       System.out.println("UserController.getUserIdByEmail: input validation passed"); |         System.out.println("UserController.getUserIdByEmail: input validation passed"); | ||||||
| 
 | 
 | ||||||
|       User user = userService.findByEmail(email.getEmail()); |         User user = userService.findByEmail(email.getEmail()); | ||||||
|       if (user == null) { |         if (user == null) { | ||||||
|          System.out.println("UserController.getUserIdByEmail, no user found with email: " + email); |             System.out.println("UserController.getUserIdByEmail, no user found with email: " + email); | ||||||
|          JsonObject obj = new JsonObject(); |             JsonObject obj = new JsonObject(); | ||||||
|          obj.addProperty("message", "No user found with this email"); |             obj.addProperty("message", "No user found with this email"); | ||||||
|          String json = new Gson().toJson(obj); |             String json = new Gson().toJson(obj); | ||||||
| 
 | 
 | ||||||
|          System.out.println("UserController.getUserIdByEmail, fails: " + json); |             System.out.println("UserController.getUserIdByEmail, fails: " + json); | ||||||
|          return ResponseEntity.badRequest().body(json); |             return ResponseEntity.badRequest().body(json); | ||||||
|       } |         } | ||||||
|       System.out.println("UserController.getUserIdByEmail, user find by email"); |         System.out.println("UserController.getUserIdByEmail, user find by email"); | ||||||
|       JsonObject obj = new JsonObject(); |         JsonObject obj = new JsonObject(); | ||||||
|       obj.addProperty("answer", user.getId()); |         obj.addProperty("answer", user.getId()); | ||||||
|       String json = new Gson().toJson(obj); |         String json = new Gson().toJson(obj); | ||||||
|       System.out.println("UserController.getUserIdByEmail " + json); |         System.out.println("UserController.getUserIdByEmail " + json); | ||||||
|       return ResponseEntity.accepted().body(json); |         return ResponseEntity.accepted().body(json); | ||||||
|    } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -32,4 +32,7 @@ public class User { | ||||||
| 
 | 
 | ||||||
|    @Column(nullable = false) |    @Column(nullable = false) | ||||||
|    private String password; |    private String password; | ||||||
|  | 
 | ||||||
|  |    @Column(nullable = false) | ||||||
|  |    private String salt; | ||||||
| } | } | ||||||
|  | @ -1,21 +1,37 @@ | ||||||
| package ch.bbw.pr.tresorbackend.service; | package ch.bbw.pr.tresorbackend.service; | ||||||
| 
 | 
 | ||||||
|  | import lombok.Value; | ||||||
|  | import org.bouncycastle.util.encoders.Hex; | ||||||
|  | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| 
 | 
 | ||||||
|  | import java.security.SecureRandom; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * PasswordEncryptionService |  * PasswordEncryptionService | ||||||
|  |  * | ||||||
|  * @author Peter Rutschmann |  * @author Peter Rutschmann | ||||||
|  */ |  */ | ||||||
| @Service | @Service | ||||||
| public class PasswordEncryptionService { | public class PasswordEncryptionService { | ||||||
|    //todo ergänzen! |  | ||||||
| 
 | 
 | ||||||
|    public PasswordEncryptionService() { |     public PasswordEncryptionService() { | ||||||
|       //todo anpassen! |         //todo anpassen! | ||||||
|    } |     } | ||||||
| 
 | 
 | ||||||
|    public String hashPassword(String password) { |     public static String generateSalt() { | ||||||
|       //todo anpassen! |         byte[] salt = new byte[5]; | ||||||
|       return password; |         new SecureRandom().nextBytes(salt); | ||||||
|    } |         return Hex.toHexString(salt); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String hashPassword(String password, String salt) { | ||||||
|  |         BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); | ||||||
|  |         String pepper = new PepperService().getPepper(); | ||||||
|  | 
 | ||||||
|  |         return encoder.encode(pepper + password ); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | record PasswordBean(String hashedPassword, String Salt) { | ||||||
| } | } | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | package ch.bbw.pr.tresorbackend.service; | ||||||
|  | 
 | ||||||
|  | import org.springframework.beans.factory.annotation.Value; | ||||||
|  | import org.springframework.stereotype.Component; | ||||||
|  | 
 | ||||||
|  | @Component | ||||||
|  | public class PepperService { | ||||||
|  | 
 | ||||||
|  |     @Value("${pepper}") | ||||||
|  |     private String pepper; | ||||||
|  | 
 | ||||||
|  |     public String getPepper() { | ||||||
|  |         return pepper; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void printPepper() { | ||||||
|  |         System.out.println("Pepper value: " + pepper); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -9,3 +9,5 @@ spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect | ||||||
| spring.jpa.hibernate.ddl-auto=update | spring.jpa.hibernate.ddl-auto=update | ||||||
| 
 | 
 | ||||||
| CROSS_ORIGIN=http://localhost:3000 | CROSS_ORIGIN=http://localhost:3000 | ||||||
|  | 
 | ||||||
|  | pepper=VfQqM | ||||||
		Loading…
	
		Reference in New Issue