diff --git a/README.md b/README.md index 245d368..009045e 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,14 @@ # Spring Boot JWT Authentication example with Spring Security & Spring Data JPA -For more detail, please visit: -> [Secure Spring Boot App with Spring Security & JWT Authentication](https://bezkoder.com/spring-boot-jwt-authentication/) - -> [For MongoDB](https://bezkoder.com/spring-boot-jwt-auth-mongodb/) +## User Registration, User Login and Authorization process. +The diagram shows flow of how we implement User Registration, User Login and Authorization process. -# Fullstack - -> [Spring Boot + Vue.js JWT Authentication](https://bezkoder.com/spring-boot-vue-js-authentication-jwt-spring-security/) +![spring-boot-jwt-authentication-spring-security-flow](spring-boot-jwt-authentication-spring-security-flow.png) -> [Spring Boot + Angular 8 JWT Authentication](https://bezkoder.com/angular-spring-boot-jwt-auth/) +## Spring Boot Server Architecture with Spring Security +You can have an overview of our Spring Boot Server with the diagram below: -> [Spring Boot + React JWT Authentication](https://bezkoder.com/spring-boot-react-jwt-auth/) +![spring-boot-jwt-authentication-spring-security-architecture](spring-boot-jwt-authentication-spring-security-architecture.png) ## Dependency – If you want to use PostgreSQL: @@ -25,8 +22,8 @@ For more detail, please visit: – or MySQL: ```xml - mysql - mysql-connector-java + com.mysql + mysql-connector-j runtime ``` @@ -50,16 +47,16 @@ bezkoder.app.jwtExpirationMs= 86400000 ``` - For MySQL ``` -spring.datasource.url= jdbc:mysql://localhost:3306/testdb?useSSL=false -spring.datasource.username= root -spring.datasource.password= 123456 +spring.datasource.url=jdbc:mysql://localhost:3306/testdb_spring?useSSL=false +spring.datasource.username=root +spring.datasource.password=123456 -spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect -spring.jpa.hibernate.ddl-auto= update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect +spring.jpa.hibernate.ddl-auto=update # App Properties -bezkoder.app.jwtSecret= bezKoderSecretKey -bezkoder.app.jwtExpirationMs= 86400000 +bezkoder.app.jwtSecret= ======================BezKoder=Spring=========================== +bezkoder.app.jwtExpirationMs=86400000 ``` ## Run Spring Boot application ``` @@ -72,3 +69,138 @@ INSERT INTO roles(name) VALUES('ROLE_USER'); INSERT INTO roles(name) VALUES('ROLE_MODERATOR'); INSERT INTO roles(name) VALUES('ROLE_ADMIN'); ``` + +For more detail, please visit: +> [Secure Spring Boot with Spring Security & JWT Authentication](https://bezkoder.com/spring-boot-jwt-authentication/) + +> [For MongoDB](https://bezkoder.com/spring-boot-jwt-auth-mongodb/) + +## Refresh Token + +![spring-boot-refresh-token-jwt-example-flow](spring-boot-refresh-token-jwt-example-flow.png) + +For instruction: [Spring Boot Refresh Token with JWT example](https://bezkoder.com/spring-boot-refresh-token-jwt/) + +## More Practice: +> [Spring Boot JWT Authentication example using HttpOnly Cookie](https://www.bezkoder.com/spring-boot-login-example-mysql/) + +> [Spring Boot File upload example with Multipart File](https://bezkoder.com/spring-boot-file-upload/) + +> [Exception handling: @RestControllerAdvice example in Spring Boot](https://bezkoder.com/spring-boot-restcontrolleradvice/) + +> [Spring Boot Repository Unit Test with @DataJpaTest](https://bezkoder.com/spring-boot-unit-test-jpa-repo-datajpatest/) + +> [Spring Boot Pagination & Sorting example](https://www.bezkoder.com/spring-boot-pagination-sorting-example/) + +> Validation: [Spring Boot Validate Request Body](https://www.bezkoder.com/spring-boot-validate-request-body/) + +> Documentation: [Spring Boot and Swagger 3 example](https://www.bezkoder.com/spring-boot-swagger-3/) + +> Caching: [Spring Boot Redis Cache example](https://www.bezkoder.com/spring-boot-redis-cache-example/) + +Associations: +> [Spring Boot One To Many example with Spring JPA, Hibernate](https://www.bezkoder.com/jpa-one-to-many/) + +> [Spring Boot Many To Many example with Spring JPA, Hibernate](https://www.bezkoder.com/jpa-many-to-many/) + +> [JPA One To One example with Spring Boot](https://www.bezkoder.com/jpa-one-to-one/) + +Deployment: +> [Deploy Spring Boot App on AWS – Elastic Beanstalk](https://www.bezkoder.com/deploy-spring-boot-aws-eb/) + +> [Docker Compose Spring Boot and MySQL example](https://www.bezkoder.com/docker-compose-spring-boot-mysql/) + +## Fullstack Authentication + +> [Spring Boot + Vue.js JWT Authentication](https://bezkoder.com/spring-boot-vue-js-authentication-jwt-spring-security/) + +> [Spring Boot + Angular 8 JWT Authentication](https://bezkoder.com/angular-spring-boot-jwt-auth/) + +> [Spring Boot + Angular 10 JWT Authentication](https://bezkoder.com/angular-10-spring-boot-jwt-auth/) + +> [Spring Boot + Angular 11 JWT Authentication](https://bezkoder.com/angular-11-spring-boot-jwt-auth/) + +> [Spring Boot + Angular 12 JWT Authentication](https://www.bezkoder.com/angular-12-spring-boot-jwt-auth/) + +> [Spring Boot + Angular 13 JWT Authentication](https://www.bezkoder.com/angular-13-spring-boot-jwt-auth/) + +> [Spring Boot + Angular 14 JWT Authentication](https://www.bezkoder.com/angular-14-spring-boot-jwt-auth/) + +> [Spring Boot + Angular 15 JWT Authentication](https://www.bezkoder.com/angular-15-spring-boot-jwt-auth/) + +> [Spring Boot + Angular 16 JWT Authentication](https://www.bezkoder.com/angular-16-spring-boot-jwt-auth/) + +> [Spring Boot + Angular 17 JWT Authentication](https://www.bezkoder.com/angular-17-spring-boot-jwt-auth/) + +> [Spring Boot + React JWT Authentication](https://bezkoder.com/spring-boot-react-jwt-auth/) + +## Fullstack CRUD App + +> [Vue.js + Spring Boot + H2 Embedded database example](https://www.bezkoder.com/spring-boot-vue-js-crud-example/) + +> [Vue.js + Spring Boot + MySQL example](https://www.bezkoder.com/spring-boot-vue-js-mysql/) + +> [Vue.js + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-vue-js-postgresql/) + +> [Angular 8 + Spring Boot + Embedded database example](https://www.bezkoder.com/angular-spring-boot-crud/) + +> [Angular 8 + Spring Boot + MySQL example](https://bezkoder.com/angular-spring-boot-crud/) + +> [Angular 8 + Spring Boot + PostgreSQL example](https://bezkoder.com/angular-spring-boot-postgresql/) + +> [Angular 10 + Spring Boot + MySQL example](https://bezkoder.com/angular-10-spring-boot-crud/) + +> [Angular 10 + Spring Boot + PostgreSQL example](https://bezkoder.com/angular-10-spring-boot-postgresql/) + +> [Angular 11 + Spring Boot + MySQL example](https://bezkoder.com/angular-11-spring-boot-crud/) + +> [Angular 11 + Spring Boot + PostgreSQL example](https://bezkoder.com/angular-11-spring-boot-postgresql/) + +> [Angular 12 + Spring Boot + Embedded database example](https://www.bezkoder.com/angular-12-spring-boot-crud/) + +> [Angular 12 + Spring Boot + MySQL example](https://www.bezkoder.com/angular-12-spring-boot-mysql/) + +> [Angular 12 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/angular-12-spring-boot-postgresql/) + +> [Angular 13 + Spring Boot + H2 Embedded Database example](https://www.bezkoder.com/spring-boot-angular-13-crud/) + +> [Angular 13 + Spring Boot + MySQL example](https://www.bezkoder.com/spring-boot-angular-13-mysql/) + +> [Angular 13 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-angular-13-postgresql/) + +> [Angular 14 + Spring Boot + H2 Embedded Database example](https://www.bezkoder.com/spring-boot-angular-14-crud/) + +> [Angular 14 + Spring Boot + MySQL example](https://www.bezkoder.com/spring-boot-angular-14-mysql/) + +> [Angular 14 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-angular-14-postgresql/) + +> [Angular 15 + Spring Boot + H2 Embedded Database example](https://www.bezkoder.com/spring-boot-angular-15-crud/) + +> [Angular 15 + Spring Boot + MySQL example](https://www.bezkoder.com/spring-boot-angular-15-mysql/) + +> [Angular 15 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-angular-15-postgresql/) + +> [Angular 16 + Spring Boot + H2 Embedded Database example](https://www.bezkoder.com/spring-boot-angular-16-crud/) + +> [Angular 16 + Spring Boot + MySQL example](https://www.bezkoder.com/spring-boot-angular-16-mysql/) + +> [Angular 16 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-angular-16-postgresql/) + +> [Angular 17 + Spring Boot + H2 Embedded Database example](https://www.bezkoder.com/spring-boot-angular-17-crud/) + +> [Angular 17 + Spring Boot + MySQL example](https://www.bezkoder.com/spring-boot-angular-17-mysql/) + +> [Angular 17 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-angular-17-postgresql/) + +> [React + Spring Boot + MySQL example](https://bezkoder.com/react-spring-boot-crud/) + +> [React + Spring Boot + PostgreSQL example](https://bezkoder.com/spring-boot-react-postgresql/) + +> [React + Spring Boot + MongoDB example](https://bezkoder.com/react-spring-boot-mongodb/) + +Run both Back-end & Front-end in one place: +> [Integrate Angular with Spring Boot Rest API](https://bezkoder.com/integrate-angular-spring-boot/) + +> [Integrate React.js with Spring Boot Rest API](https://bezkoder.com/integrate-reactjs-spring-boot/) + +> [Integrate Vue.js with Spring Boot Rest API](https://bezkoder.com/integrate-vue-spring-boot/) diff --git a/pom.xml b/pom.xml index 048d6d3..23a0aba 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 2.1.8.RELEASE + 3.1.0 com.bezkoder @@ -16,7 +16,7 @@ Demo project for Spring Boot Security - JWT - 1.8 + 17 @@ -30,21 +30,40 @@ spring-boot-starter-security + + org.springframework.boot + spring-boot-starter-validation + + org.springframework.boot spring-boot-starter-web - org.postgresql - postgresql + com.mysql + mysql-connector-j runtime io.jsonwebtoken - jjwt - 0.9.1 + jjwt-api + 0.11.5 + + + + io.jsonwebtoken + jjwt-impl + 0.11.5 + runtime + + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + runtime @@ -52,7 +71,7 @@ spring-boot-starter-test test - + org.springframework.security spring-security-test diff --git a/spring-boot-jwt-authentication-spring-security-architecture.png b/spring-boot-jwt-authentication-spring-security-architecture.png new file mode 100644 index 0000000..b238cb3 Binary files /dev/null and b/spring-boot-jwt-authentication-spring-security-architecture.png differ diff --git a/spring-boot-jwt-authentication-spring-security-flow.png b/spring-boot-jwt-authentication-spring-security-flow.png new file mode 100644 index 0000000..95b5608 Binary files /dev/null and b/spring-boot-jwt-authentication-spring-security-flow.png differ diff --git a/spring-boot-refresh-token-jwt-example-flow.png b/spring-boot-refresh-token-jwt-example-flow.png new file mode 100644 index 0000000..5f3d258 Binary files /dev/null and b/spring-boot-refresh-token-jwt-example-flow.png differ diff --git a/src/main/java/com/bezkoder/springjwt/SpringBootSecurityJwtApplication.java b/src/main/java/com/bezkoder/springjwt/SpringBootSecurityJwtApplication.java index d13abd7..c723518 100644 --- a/src/main/java/com/bezkoder/springjwt/SpringBootSecurityJwtApplication.java +++ b/src/main/java/com/bezkoder/springjwt/SpringBootSecurityJwtApplication.java @@ -7,7 +7,7 @@ public class SpringBootSecurityJwtApplication { public static void main(String[] args) { - SpringApplication.run(SpringBootSecurityJwtApplication.class, args); + SpringApplication.run(SpringBootSecurityJwtApplication.class, args); } } diff --git a/src/main/java/com/bezkoder/springjwt/controllers/AuthController.java b/src/main/java/com/bezkoder/springjwt/controllers/AuthController.java index e598702..eb54879 100644 --- a/src/main/java/com/bezkoder/springjwt/controllers/AuthController.java +++ b/src/main/java/com/bezkoder/springjwt/controllers/AuthController.java @@ -5,7 +5,7 @@ import java.util.Set; import java.util.stream.Collectors; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; @@ -36,94 +36,94 @@ @RestController @RequestMapping("/api/auth") public class AuthController { - @Autowired - AuthenticationManager authenticationManager; - - @Autowired - UserRepository userRepository; - - @Autowired - RoleRepository roleRepository; - - @Autowired - PasswordEncoder encoder; - - @Autowired - JwtUtils jwtUtils; - - @PostMapping("/signin") - public ResponseEntity authenticateUser(@Valid @RequestBody LoginRequest loginRequest) { - - Authentication authentication = authenticationManager.authenticate( - new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())); - - SecurityContextHolder.getContext().setAuthentication(authentication); - String jwt = jwtUtils.generateJwtToken(authentication); - - UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal(); - List roles = userDetails.getAuthorities().stream() - .map(item -> item.getAuthority()) - .collect(Collectors.toList()); - - return ResponseEntity.ok(new JwtResponse(jwt, - userDetails.getId(), - userDetails.getUsername(), - userDetails.getEmail(), - roles)); - } - - @PostMapping("/signup") - public ResponseEntity registerUser(@Valid @RequestBody SignupRequest signUpRequest) { - if (userRepository.existsByUsername(signUpRequest.getUsername())) { - return ResponseEntity - .badRequest() - .body(new MessageResponse("Error: Username is already taken!")); - } - - if (userRepository.existsByEmail(signUpRequest.getEmail())) { - return ResponseEntity - .badRequest() - .body(new MessageResponse("Error: Email is already in use!")); - } - - // Create new user's account - User user = new User(signUpRequest.getUsername(), - signUpRequest.getEmail(), - encoder.encode(signUpRequest.getPassword())); - - Set strRoles = signUpRequest.getRole(); - Set roles = new HashSet<>(); - - if (strRoles == null) { - Role userRole = roleRepository.findByName(ERole.ROLE_USER) - .orElseThrow(() -> new RuntimeException("Error: Role is not found.")); - roles.add(userRole); - } else { - strRoles.forEach(role -> { - switch (role) { - case "admin": - Role adminRole = roleRepository.findByName(ERole.ROLE_ADMIN) - .orElseThrow(() -> new RuntimeException("Error: Role is not found.")); - roles.add(adminRole); - - break; - case "mod": - Role modRole = roleRepository.findByName(ERole.ROLE_MODERATOR) - .orElseThrow(() -> new RuntimeException("Error: Role is not found.")); - roles.add(modRole); - - break; - default: - Role userRole = roleRepository.findByName(ERole.ROLE_USER) - .orElseThrow(() -> new RuntimeException("Error: Role is not found.")); - roles.add(userRole); - } - }); - } - - user.setRoles(roles); - userRepository.save(user); - - return ResponseEntity.ok(new MessageResponse("User registered successfully!")); - } + @Autowired + AuthenticationManager authenticationManager; + + @Autowired + UserRepository userRepository; + + @Autowired + RoleRepository roleRepository; + + @Autowired + PasswordEncoder encoder; + + @Autowired + JwtUtils jwtUtils; + + @PostMapping("/signin") + public ResponseEntity authenticateUser(@Valid @RequestBody LoginRequest loginRequest) { + + Authentication authentication = authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())); + + SecurityContextHolder.getContext().setAuthentication(authentication); + String jwt = jwtUtils.generateJwtToken(authentication); + + UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal(); + List roles = userDetails.getAuthorities().stream() + .map(item -> item.getAuthority()) + .collect(Collectors.toList()); + + return ResponseEntity.ok(new JwtResponse(jwt, + userDetails.getId(), + userDetails.getUsername(), + userDetails.getEmail(), + roles)); + } + + @PostMapping("/signup") + public ResponseEntity registerUser(@Valid @RequestBody SignupRequest signUpRequest) { + if (userRepository.existsByUsername(signUpRequest.getUsername())) { + return ResponseEntity + .badRequest() + .body(new MessageResponse("Error: Username is already taken!")); + } + + if (userRepository.existsByEmail(signUpRequest.getEmail())) { + return ResponseEntity + .badRequest() + .body(new MessageResponse("Error: Email is already in use!")); + } + + // Create new user's account + User user = new User(signUpRequest.getUsername(), + signUpRequest.getEmail(), + encoder.encode(signUpRequest.getPassword())); + + Set strRoles = signUpRequest.getRole(); + Set roles = new HashSet<>(); + + if (strRoles == null) { + Role userRole = roleRepository.findByName(ERole.ROLE_USER) + .orElseThrow(() -> new RuntimeException("Error: Role is not found.")); + roles.add(userRole); + } else { + strRoles.forEach(role -> { + switch (role) { + case "admin": + Role adminRole = roleRepository.findByName(ERole.ROLE_ADMIN) + .orElseThrow(() -> new RuntimeException("Error: Role is not found.")); + roles.add(adminRole); + + break; + case "mod": + Role modRole = roleRepository.findByName(ERole.ROLE_MODERATOR) + .orElseThrow(() -> new RuntimeException("Error: Role is not found.")); + roles.add(modRole); + + break; + default: + Role userRole = roleRepository.findByName(ERole.ROLE_USER) + .orElseThrow(() -> new RuntimeException("Error: Role is not found.")); + roles.add(userRole); + } + }); + } + + user.setRoles(roles); + userRepository.save(user); + + return ResponseEntity.ok(new MessageResponse("User registered successfully!")); + } } diff --git a/src/main/java/com/bezkoder/springjwt/controllers/TestController.java b/src/main/java/com/bezkoder/springjwt/controllers/TestController.java index 298a7ea..e03b5cb 100644 --- a/src/main/java/com/bezkoder/springjwt/controllers/TestController.java +++ b/src/main/java/com/bezkoder/springjwt/controllers/TestController.java @@ -10,26 +10,26 @@ @RestController @RequestMapping("/api/test") public class TestController { - @GetMapping("/all") - public String allAccess() { - return "Public Content."; - } - - @GetMapping("/user") - @PreAuthorize("hasRole('USER') or hasRole('MODERATOR') or hasRole('ADMIN')") - public String userAccess() { - return "User Content."; - } + @GetMapping("/all") + public String allAccess() { + return "Public Content."; + } - @GetMapping("/mod") - @PreAuthorize("hasRole('MODERATOR')") - public String moderatorAccess() { - return "Moderator Board."; - } + @GetMapping("/user") + @PreAuthorize("hasRole('USER') or hasRole('MODERATOR') or hasRole('ADMIN')") + public String userAccess() { + return "User Content."; + } - @GetMapping("/admin") - @PreAuthorize("hasRole('ADMIN')") - public String adminAccess() { - return "Admin Board."; - } + @GetMapping("/mod") + @PreAuthorize("hasRole('MODERATOR')") + public String moderatorAccess() { + return "Moderator Board."; + } + + @GetMapping("/admin") + @PreAuthorize("hasRole('ADMIN')") + public String adminAccess() { + return "Admin Board."; + } } diff --git a/src/main/java/com/bezkoder/springjwt/models/ERole.java b/src/main/java/com/bezkoder/springjwt/models/ERole.java index 9acf4a4..a113c68 100644 --- a/src/main/java/com/bezkoder/springjwt/models/ERole.java +++ b/src/main/java/com/bezkoder/springjwt/models/ERole.java @@ -1,7 +1,7 @@ package com.bezkoder.springjwt.models; public enum ERole { - ROLE_USER, - ROLE_MODERATOR, - ROLE_ADMIN + ROLE_USER, + ROLE_MODERATOR, + ROLE_ADMIN } diff --git a/src/main/java/com/bezkoder/springjwt/models/Role.java b/src/main/java/com/bezkoder/springjwt/models/Role.java index 44b82ad..8eb847f 100644 --- a/src/main/java/com/bezkoder/springjwt/models/Role.java +++ b/src/main/java/com/bezkoder/springjwt/models/Role.java @@ -1,39 +1,39 @@ package com.bezkoder.springjwt.models; -import javax.persistence.*; +import jakarta.persistence.*; @Entity @Table(name = "roles") public class Role { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Integer id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; - @Enumerated(EnumType.STRING) - @Column(length = 20) - private ERole name; + @Enumerated(EnumType.STRING) + @Column(length = 20) + private ERole name; - public Role() { + public Role() { - } + } - public Role(ERole name) { - this.name = name; - } + public Role(ERole name) { + this.name = name; + } - public Integer getId() { - return id; - } + public Integer getId() { + return id; + } - public void setId(Integer id) { - this.id = id; - } + public void setId(Integer id) { + this.id = id; + } - public ERole getName() { - return name; - } + public ERole getName() { + return name; + } - public void setName(ERole name) { - this.name = name; - } + public void setName(ERole name) { + this.name = name; + } } \ No newline at end of file diff --git a/src/main/java/com/bezkoder/springjwt/models/User.java b/src/main/java/com/bezkoder/springjwt/models/User.java index 6e3eaa2..2ad0c5d 100644 --- a/src/main/java/com/bezkoder/springjwt/models/User.java +++ b/src/main/java/com/bezkoder/springjwt/models/User.java @@ -3,87 +3,87 @@ import java.util.HashSet; import java.util.Set; -import javax.persistence.*; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; +import jakarta.persistence.*; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; @Entity -@Table( name = "users", - uniqueConstraints = { - @UniqueConstraint(columnNames = "username"), - @UniqueConstraint(columnNames = "email") - }) +@Table(name = "users", + uniqueConstraints = { + @UniqueConstraint(columnNames = "username"), + @UniqueConstraint(columnNames = "email") + }) public class User { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotBlank - @Size(max = 20) - private String username; - - @NotBlank - @Size(max = 50) - @Email - private String email; - - @NotBlank - @Size(max = 120) - private String password; - - @ManyToMany(fetch = FetchType.LAZY) - @JoinTable( name = "user_roles", - joinColumns = @JoinColumn(name = "user_id"), - inverseJoinColumns = @JoinColumn(name = "role_id")) - private Set roles = new HashSet<>(); - - public User() { - } - - public User(String username, String email, String password) { - this.username = username; - this.email = email; - this.password = password; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Set getRoles() { - return roles; - } - - public void setRoles(Set roles) { - this.roles = roles; - } + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotBlank + @Size(max = 20) + private String username; + + @NotBlank + @Size(max = 50) + @Email + private String email; + + @NotBlank + @Size(max = 120) + private String password; + + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable( name = "user_roles", + joinColumns = @JoinColumn(name = "user_id"), + inverseJoinColumns = @JoinColumn(name = "role_id")) + private Set roles = new HashSet<>(); + + public User() { + } + + public User(String username, String email, String password) { + this.username = username; + this.email = email; + this.password = password; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Set getRoles() { + return roles; + } + + public void setRoles(Set roles) { + this.roles = roles; + } } diff --git a/src/main/java/com/bezkoder/springjwt/payload/request/LoginRequest.java b/src/main/java/com/bezkoder/springjwt/payload/request/LoginRequest.java index e0e7f9f..de32475 100644 --- a/src/main/java/com/bezkoder/springjwt/payload/request/LoginRequest.java +++ b/src/main/java/com/bezkoder/springjwt/payload/request/LoginRequest.java @@ -1,10 +1,10 @@ package com.bezkoder.springjwt.payload.request; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotBlank; public class LoginRequest { @NotBlank - private String username; + private String username; @NotBlank private String password; diff --git a/src/main/java/com/bezkoder/springjwt/payload/request/SignupRequest.java b/src/main/java/com/bezkoder/springjwt/payload/request/SignupRequest.java index 515e0a5..ccbb562 100644 --- a/src/main/java/com/bezkoder/springjwt/payload/request/SignupRequest.java +++ b/src/main/java/com/bezkoder/springjwt/payload/request/SignupRequest.java @@ -2,53 +2,53 @@ import java.util.Set; -import javax.validation.constraints.*; - +import jakarta.validation.constraints.*; + public class SignupRequest { - @NotBlank - @Size(min = 3, max = 20) - private String username; - - @NotBlank - @Size(max = 50) - @Email - private String email; - - private Set role; - - @NotBlank - @Size(min = 6, max = 40) - private String password; - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Set getRole() { - return this.role; - } - - public void setRole(Set role) { - this.role = role; - } + @NotBlank + @Size(min = 3, max = 20) + private String username; + + @NotBlank + @Size(max = 50) + @Email + private String email; + + private Set role; + + @NotBlank + @Size(min = 6, max = 40) + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Set getRole() { + return this.role; + } + + public void setRole(Set role) { + this.role = role; + } } diff --git a/src/main/java/com/bezkoder/springjwt/payload/response/JwtResponse.java b/src/main/java/com/bezkoder/springjwt/payload/response/JwtResponse.java index 35ae5a4..ac387f0 100644 --- a/src/main/java/com/bezkoder/springjwt/payload/response/JwtResponse.java +++ b/src/main/java/com/bezkoder/springjwt/payload/response/JwtResponse.java @@ -3,62 +3,62 @@ import java.util.List; public class JwtResponse { - private String token; - private String type = "Bearer"; - private Long id; - private String username; - private String email; - private List roles; + private String token; + private String type = "Bearer"; + private Long id; + private String username; + private String email; + private List roles; - public JwtResponse(String accessToken, Long id, String username, String email, List roles) { - this.token = accessToken; - this.id = id; - this.username = username; - this.email = email; - this.roles = roles; - } + public JwtResponse(String accessToken, Long id, String username, String email, List roles) { + this.token = accessToken; + this.id = id; + this.username = username; + this.email = email; + this.roles = roles; + } - public String getAccessToken() { - return token; - } + public String getAccessToken() { + return token; + } - public void setAccessToken(String accessToken) { - this.token = accessToken; - } + public void setAccessToken(String accessToken) { + this.token = accessToken; + } - public String getTokenType() { - return type; - } + public String getTokenType() { + return type; + } - public void setTokenType(String tokenType) { - this.type = tokenType; - } + public void setTokenType(String tokenType) { + this.type = tokenType; + } - public Long getId() { - return id; - } + public Long getId() { + return id; + } - public void setId(Long id) { - this.id = id; - } + public void setId(Long id) { + this.id = id; + } - public String getEmail() { - return email; - } + public String getEmail() { + return email; + } - public void setEmail(String email) { - this.email = email; - } + public void setEmail(String email) { + this.email = email; + } - public String getUsername() { - return username; - } + public String getUsername() { + return username; + } - public void setUsername(String username) { - this.username = username; - } + public void setUsername(String username) { + this.username = username; + } - public List getRoles() { - return roles; - } + public List getRoles() { + return roles; + } } diff --git a/src/main/java/com/bezkoder/springjwt/payload/response/MessageResponse.java b/src/main/java/com/bezkoder/springjwt/payload/response/MessageResponse.java index 4a3a59f..068e179 100644 --- a/src/main/java/com/bezkoder/springjwt/payload/response/MessageResponse.java +++ b/src/main/java/com/bezkoder/springjwt/payload/response/MessageResponse.java @@ -1,17 +1,17 @@ package com.bezkoder.springjwt.payload.response; public class MessageResponse { - private String message; + private String message; - public MessageResponse(String message) { - this.message = message; - } + public MessageResponse(String message) { + this.message = message; + } - public String getMessage() { - return message; - } + public String getMessage() { + return message; + } - public void setMessage(String message) { - this.message = message; - } + public void setMessage(String message) { + this.message = message; + } } diff --git a/src/main/java/com/bezkoder/springjwt/repository/RoleRepository.java b/src/main/java/com/bezkoder/springjwt/repository/RoleRepository.java index 06aa459..a1882d0 100644 --- a/src/main/java/com/bezkoder/springjwt/repository/RoleRepository.java +++ b/src/main/java/com/bezkoder/springjwt/repository/RoleRepository.java @@ -10,5 +10,5 @@ @Repository public interface RoleRepository extends JpaRepository { - Optional findByName(ERole name); + Optional findByName(ERole name); } diff --git a/src/main/java/com/bezkoder/springjwt/repository/UserRepository.java b/src/main/java/com/bezkoder/springjwt/repository/UserRepository.java index 74f2df9..d48a98c 100644 --- a/src/main/java/com/bezkoder/springjwt/repository/UserRepository.java +++ b/src/main/java/com/bezkoder/springjwt/repository/UserRepository.java @@ -9,9 +9,9 @@ @Repository public interface UserRepository extends JpaRepository { - Optional findByUsername(String username); + Optional findByUsername(String username); - Boolean existsByUsername(String username); + Boolean existsByUsername(String username); - Boolean existsByEmail(String email); + Boolean existsByEmail(String email); } diff --git a/src/main/java/com/bezkoder/springjwt/security/WebSecurityConfig.java b/src/main/java/com/bezkoder/springjwt/security/WebSecurityConfig.java index 405cf6b..d7565d1 100644 --- a/src/main/java/com/bezkoder/springjwt/security/WebSecurityConfig.java +++ b/src/main/java/com/bezkoder/springjwt/security/WebSecurityConfig.java @@ -4,14 +4,17 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +//import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +//import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import com.bezkoder.springjwt.security.jwt.AuthEntryPointJwt; @@ -19,48 +22,80 @@ import com.bezkoder.springjwt.security.services.UserDetailsServiceImpl; @Configuration -@EnableWebSecurity -@EnableGlobalMethodSecurity( - // securedEnabled = true, - // jsr250Enabled = true, - prePostEnabled = true) -public class WebSecurityConfig extends WebSecurityConfigurerAdapter { - @Autowired - UserDetailsServiceImpl userDetailsService; +@EnableMethodSecurity +// (securedEnabled = true, +// jsr250Enabled = true, +// prePostEnabled = true) // by default +public class WebSecurityConfig { // extends WebSecurityConfigurerAdapter { + @Autowired + UserDetailsServiceImpl userDetailsService; - @Autowired - private AuthEntryPointJwt unauthorizedHandler; + @Autowired + private AuthEntryPointJwt unauthorizedHandler; - @Bean - public AuthTokenFilter authenticationJwtTokenFilter() { - return new AuthTokenFilter(); - } + @Bean + public AuthTokenFilter authenticationJwtTokenFilter() { + return new AuthTokenFilter(); + } - @Override - public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { - authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); - } +// @Override +// public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { +// authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); +// } + + @Bean + public DaoAuthenticationProvider authenticationProvider() { + DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); + + authProvider.setUserDetailsService(userDetailsService); + authProvider.setPasswordEncoder(passwordEncoder()); + + return authProvider; + } - @Bean - @Override - public AuthenticationManager authenticationManagerBean() throws Exception { - return super.authenticationManagerBean(); - } +// @Bean +// @Override +// public AuthenticationManager authenticationManagerBean() throws Exception { +// return super.authenticationManagerBean(); +// } + + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { + return authConfig.getAuthenticationManager(); + } - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } - @Override - protected void configure(HttpSecurity http) throws Exception { - http.cors().and().csrf().disable() - .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() - .authorizeRequests().antMatchers("/api/auth/**").permitAll() - .antMatchers("/api/test/**").permitAll() - .anyRequest().authenticated(); +// @Override +// protected void configure(HttpSecurity http) throws Exception { +// http.cors().and().csrf().disable() +// .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() +// .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() +// .authorizeRequests().antMatchers("/api/auth/**").permitAll() +// .antMatchers("/api/test/**").permitAll() +// .anyRequest().authenticated(); +// +// http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class); +// } + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http.csrf(csrf -> csrf.disable()) + .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler)) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .authorizeHttpRequests(auth -> + auth.requestMatchers("/api/auth/**").permitAll() + .requestMatchers("/api/test/**").permitAll() + .anyRequest().authenticated() + ); + + http.authenticationProvider(authenticationProvider()); - http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class); - } + http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class); + + return http.build(); + } } diff --git a/src/main/java/com/bezkoder/springjwt/security/jwt/AuthEntryPointJwt.java b/src/main/java/com/bezkoder/springjwt/security/jwt/AuthEntryPointJwt.java index b7e2647..232ba13 100644 --- a/src/main/java/com/bezkoder/springjwt/security/jwt/AuthEntryPointJwt.java +++ b/src/main/java/com/bezkoder/springjwt/security/jwt/AuthEntryPointJwt.java @@ -1,27 +1,43 @@ package com.bezkoder.springjwt.security.jwt; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; +import com.fasterxml.jackson.databind.ObjectMapper; + @Component public class AuthEntryPointJwt implements AuthenticationEntryPoint { - private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class); + private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class); + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) + throws IOException, ServletException { + logger.error("Unauthorized error: {}", authException.getMessage()); + + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + + final Map body = new HashMap<>(); + body.put("status", HttpServletResponse.SC_UNAUTHORIZED); + body.put("error", "Unauthorized"); + body.put("message", authException.getMessage()); + body.put("path", request.getServletPath()); - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, - AuthenticationException authException) throws IOException, ServletException { - logger.error("Unauthorized error: {}", authException.getMessage()); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized"); - } + final ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(response.getOutputStream(), body); + } } diff --git a/src/main/java/com/bezkoder/springjwt/security/jwt/AuthTokenFilter.java b/src/main/java/com/bezkoder/springjwt/security/jwt/AuthTokenFilter.java index 4a906a8..f2e31ef 100644 --- a/src/main/java/com/bezkoder/springjwt/security/jwt/AuthTokenFilter.java +++ b/src/main/java/com/bezkoder/springjwt/security/jwt/AuthTokenFilter.java @@ -2,10 +2,10 @@ import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,43 +20,46 @@ import com.bezkoder.springjwt.security.services.UserDetailsServiceImpl; public class AuthTokenFilter extends OncePerRequestFilter { - @Autowired - private JwtUtils jwtUtils; + @Autowired + private JwtUtils jwtUtils; - @Autowired - private UserDetailsServiceImpl userDetailsService; + @Autowired + private UserDetailsServiceImpl userDetailsService; - private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class); + private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class); - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException { - try { - String jwt = parseJwt(request); - if (jwt != null && jwtUtils.validateJwtToken(jwt)) { - String username = jwtUtils.getUserNameFromJwtToken(jwt); + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + try { + String jwt = parseJwt(request); + if (jwt != null && jwtUtils.validateJwtToken(jwt)) { + String username = jwtUtils.getUserNameFromJwtToken(jwt); - UserDetails userDetails = userDetailsService.loadUserByUsername(username); - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( - userDetails, null, userDetails.getAuthorities()); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken( + userDetails, + null, + userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - } catch (Exception e) { - logger.error("Cannot set user authentication: {}", e); - } + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } catch (Exception e) { + logger.error("Cannot set user authentication: {}", e); + } - filterChain.doFilter(request, response); - } + filterChain.doFilter(request, response); + } - private String parseJwt(HttpServletRequest request) { - String headerAuth = request.getHeader("Authorization"); + private String parseJwt(HttpServletRequest request) { + String headerAuth = request.getHeader("Authorization"); - if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) { - return headerAuth.substring(7, headerAuth.length()); - } + if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) { + return headerAuth.substring(7); + } - return null; - } + return null; + } } diff --git a/src/main/java/com/bezkoder/springjwt/security/jwt/JwtUtils.java b/src/main/java/com/bezkoder/springjwt/security/jwt/JwtUtils.java index 400b563..a031392 100644 --- a/src/main/java/com/bezkoder/springjwt/security/jwt/JwtUtils.java +++ b/src/main/java/com/bezkoder/springjwt/security/jwt/JwtUtils.java @@ -1,5 +1,6 @@ package com.bezkoder.springjwt.security.jwt; +import java.security.Key; import java.util.Date; import org.slf4j.Logger; @@ -10,49 +11,54 @@ import com.bezkoder.springjwt.security.services.UserDetailsImpl; import io.jsonwebtoken.*; +import io.jsonwebtoken.io.Decoders; +import io.jsonwebtoken.security.Keys; @Component public class JwtUtils { - private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class); - - @Value("${bezkoder.app.jwtSecret}") - private String jwtSecret; - - @Value("${bezkoder.app.jwtExpirationMs}") - private int jwtExpirationMs; - - public String generateJwtToken(Authentication authentication) { - - UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal(); - - return Jwts.builder() - .setSubject((userPrincipal.getUsername())) - .setIssuedAt(new Date()) - .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs)) - .signWith(SignatureAlgorithm.HS512, jwtSecret) - .compact(); - } - - public String getUserNameFromJwtToken(String token) { - return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject(); - } - - public boolean validateJwtToken(String authToken) { - try { - Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken); - return true; - } catch (SignatureException e) { - logger.error("Invalid JWT signature: {}", e.getMessage()); - } catch (MalformedJwtException e) { - logger.error("Invalid JWT token: {}", e.getMessage()); - } catch (ExpiredJwtException e) { - logger.error("JWT token is expired: {}", e.getMessage()); - } catch (UnsupportedJwtException e) { - logger.error("JWT token is unsupported: {}", e.getMessage()); - } catch (IllegalArgumentException e) { - logger.error("JWT claims string is empty: {}", e.getMessage()); - } - - return false; - } + private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class); + + @Value("${bezkoder.app.jwtSecret}") + private String jwtSecret; + + @Value("${bezkoder.app.jwtExpirationMs}") + private int jwtExpirationMs; + + public String generateJwtToken(Authentication authentication) { + + UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal(); + + return Jwts.builder() + .setSubject((userPrincipal.getUsername())) + .setIssuedAt(new Date()) + .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs)) + .signWith(key(), SignatureAlgorithm.HS256) + .compact(); + } + + private Key key() { + return Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtSecret)); + } + + public String getUserNameFromJwtToken(String token) { + return Jwts.parserBuilder().setSigningKey(key()).build() + .parseClaimsJws(token).getBody().getSubject(); + } + + public boolean validateJwtToken(String authToken) { + try { + Jwts.parserBuilder().setSigningKey(key()).build().parse(authToken); + return true; + } catch (MalformedJwtException e) { + logger.error("Invalid JWT token: {}", e.getMessage()); + } catch (ExpiredJwtException e) { + logger.error("JWT token is expired: {}", e.getMessage()); + } catch (UnsupportedJwtException e) { + logger.error("JWT token is unsupported: {}", e.getMessage()); + } catch (IllegalArgumentException e) { + logger.error("JWT claims string is empty: {}", e.getMessage()); + } + + return false; + } } diff --git a/src/main/java/com/bezkoder/springjwt/security/services/UserDetailsImpl.java b/src/main/java/com/bezkoder/springjwt/security/services/UserDetailsImpl.java index fafc5a9..6452f34 100644 --- a/src/main/java/com/bezkoder/springjwt/security/services/UserDetailsImpl.java +++ b/src/main/java/com/bezkoder/springjwt/security/services/UserDetailsImpl.java @@ -13,91 +13,91 @@ import com.fasterxml.jackson.annotation.JsonIgnore; public class UserDetailsImpl implements UserDetails { - private static final long serialVersionUID = 1L; - - private Long id; - - private String username; - - private String email; - - @JsonIgnore - private String password; - - private Collection authorities; - - public UserDetailsImpl(Long id, String username, String email, String password, - Collection authorities) { - this.id = id; - this.username = username; - this.email = email; - this.password = password; - this.authorities = authorities; - } - - public static UserDetailsImpl build(User user) { - List authorities = user.getRoles().stream() - .map(role -> new SimpleGrantedAuthority(role.getName().name())) - .collect(Collectors.toList()); - - return new UserDetailsImpl( - user.getId(), - user.getUsername(), - user.getEmail(), - user.getPassword(), - authorities); - } - - @Override - public Collection getAuthorities() { - return authorities; - } - - public Long getId() { - return id; - } - - public String getEmail() { - return email; - } - - @Override - public String getPassword() { - return password; - } - - @Override - public String getUsername() { - return username; - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return true; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - UserDetailsImpl user = (UserDetailsImpl) o; - return Objects.equals(id, user.id); - } + private static final long serialVersionUID = 1L; + + private Long id; + + private String username; + + private String email; + + @JsonIgnore + private String password; + + private Collection authorities; + + public UserDetailsImpl(Long id, String username, String email, String password, + Collection authorities) { + this.id = id; + this.username = username; + this.email = email; + this.password = password; + this.authorities = authorities; + } + + public static UserDetailsImpl build(User user) { + List authorities = user.getRoles().stream() + .map(role -> new SimpleGrantedAuthority(role.getName().name())) + .collect(Collectors.toList()); + + return new UserDetailsImpl( + user.getId(), + user.getUsername(), + user.getEmail(), + user.getPassword(), + authorities); + } + + @Override + public Collection getAuthorities() { + return authorities; + } + + public Long getId() { + return id; + } + + public String getEmail() { + return email; + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getUsername() { + return username; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + UserDetailsImpl user = (UserDetailsImpl) o; + return Objects.equals(id, user.id); + } } diff --git a/src/main/java/com/bezkoder/springjwt/security/services/UserDetailsServiceImpl.java b/src/main/java/com/bezkoder/springjwt/security/services/UserDetailsServiceImpl.java index 9a3ed41..de65d7e 100644 --- a/src/main/java/com/bezkoder/springjwt/security/services/UserDetailsServiceImpl.java +++ b/src/main/java/com/bezkoder/springjwt/security/services/UserDetailsServiceImpl.java @@ -12,16 +12,16 @@ @Service public class UserDetailsServiceImpl implements UserDetailsService { - @Autowired - UserRepository userRepository; + @Autowired + UserRepository userRepository; - @Override - @Transactional - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - User user = userRepository.findByUsername(username) - .orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username)); + @Override + @Transactional + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + User user = userRepository.findByUsername(username) + .orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username)); - return UserDetailsImpl.build(user); - } + return UserDetailsImpl.build(user); + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index eea124f..481d5ed 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,15 +1,10 @@ -## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties) -spring.datasource.url= jdbc:postgresql://localhost:5432/testdb -spring.datasource.username= postgres -spring.datasource.password= 123 +spring.datasource.url=jdbc:mysql://localhost:3306/testdb_spring?useSSL=false +spring.datasource.username=root +spring.datasource.password=123456 -spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation= true -# The SQL dialect makes Hibernate generate better SQL for the chosen database -spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect - -# Hibernate ddl auto (create, create-drop, validate, update) -spring.jpa.hibernate.ddl-auto= update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect +spring.jpa.hibernate.ddl-auto=update # App Properties -bezkoder.app.jwtSecret= bezKoderSecretKey -bezkoder.app.jwtExpirationMs= 86400000 \ No newline at end of file +bezkoder.app.jwtSecret= ======================BezKoder=Spring=========================== +bezkoder.app.jwtExpirationMs=86400000 \ No newline at end of file diff --git a/src/test/java/com/bezkoder/springjwt/SpringBootSecurityJwtApplicationTests.java b/src/test/java/com/bezkoder/springjwt/SpringBootSecurityJwtApplicationTests.java index 60fe0c3..42ffdd0 100644 --- a/src/test/java/com/bezkoder/springjwt/SpringBootSecurityJwtApplicationTests.java +++ b/src/test/java/com/bezkoder/springjwt/SpringBootSecurityJwtApplicationTests.java @@ -1,11 +1,8 @@ package com.bezkoder.springjwt; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest public class SpringBootSecurityJwtApplicationTests {