-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from MinhQuan992/booking-module-service
feat: create spring security for booking service
- Loading branch information
Showing
30 changed files
with
453 additions
and
48 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,42 @@ | ||
package org.example; | ||
|
||
import org.example.model.UserRole; | ||
import org.example.model.UserAccount; | ||
import org.example.service.UserService; | ||
import org.springframework.boot.CommandLineRunner; | ||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
import org.springframework.security.crypto.password.PasswordEncoder; | ||
|
||
import java.util.ArrayList; | ||
|
||
@SpringBootApplication | ||
public class BookingApplication | ||
{ | ||
public static void main( String[] args ) { | ||
SpringApplication.run(BookingApplication.class, args); | ||
} | ||
|
||
@Bean | ||
PasswordEncoder passwordEncoder() { | ||
return new BCryptPasswordEncoder(); | ||
} | ||
|
||
// @Bean | ||
// CommandLineRunner run(UserService userService) { | ||
// return args -> { | ||
// userService.addRole(new UserRole(null, "ROLE_USER")); | ||
// userService.addRole(new UserRole(null, "ROLE_ADMIN")); | ||
// | ||
// userService.addUser(new UserAccount(null, "Minh Quan", "minhquan", "1234", new ArrayList<>())); | ||
// userService.addUser(new UserAccount(null, "Minh Hien", "minhhien", "1234", new ArrayList<>())); | ||
// userService.addUser(new UserAccount(null, "Le Anh", "leanh", "1234", new ArrayList<>())); | ||
// | ||
// userService.addRoleToUser("minhquan", "ROLE_USER"); | ||
// userService.addRoleToUser("leanh", "ROLE_USER"); | ||
// userService.addRoleToUser("leanh", "ROLE_ADMIN"); | ||
// }; | ||
// } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
booking/src/main/java/org/example/controller/UserController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package org.example.controller; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.example.model.RoleToUserForm; | ||
import org.example.model.UserRole; | ||
import org.example.model.UserAccount; | ||
import org.example.service.UserService; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder; | ||
|
||
import java.net.URI; | ||
|
||
@Slf4j | ||
@RestController | ||
@RequestMapping("api") | ||
@AllArgsConstructor | ||
public class UserController { | ||
private final UserService userService; | ||
|
||
@GetMapping("/users") | ||
public ResponseEntity<Iterable<UserAccount>> getAllUsers() { | ||
return new ResponseEntity<>(userService.getAllUsers(), HttpStatus.OK); | ||
} | ||
|
||
@GetMapping("/user/{username}") | ||
public ResponseEntity<UserAccount> getUserByUsername(@PathVariable("username") String username) { | ||
return new ResponseEntity<>(userService.getUserByUsername(username), HttpStatus.OK); | ||
} | ||
|
||
@PostMapping("/user/save") | ||
public ResponseEntity<UserAccount> saveUser(@RequestBody UserAccount userAccount) { | ||
URI uri = URI.create(ServletUriComponentsBuilder.fromCurrentContextPath().path("/api/user/save").toUriString()); | ||
return ResponseEntity.created(uri).body(userService.addUser(userAccount)); | ||
} | ||
|
||
@PostMapping("/role/save") | ||
public ResponseEntity<UserRole> saveRole(@RequestBody UserRole userRole) { | ||
URI uri = URI.create(ServletUriComponentsBuilder.fromCurrentContextPath().path("/api/role/save").toUriString()); | ||
return ResponseEntity.created(uri).body(userService.addRole(userRole)); | ||
} | ||
|
||
@PostMapping("/role/addtouser") | ||
public ResponseEntity<?> addRoleToUser(@RequestBody RoleToUserForm roleToUserForm) { | ||
userService.addRoleToUser(roleToUserForm.getUsername(), roleToUserForm.getRoleName()); | ||
return ResponseEntity.ok().build(); | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
booking/src/main/java/org/example/filter/CustomAuthenticationFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package org.example.filter; | ||
|
||
import com.auth0.jwt.JWT; | ||
import com.auth0.jwt.algorithms.Algorithm; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.security.authentication.AuthenticationManager; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.AuthenticationException; | ||
import org.springframework.security.core.GrantedAuthority; | ||
import org.springframework.security.core.userdetails.User; | ||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
|
||
import javax.servlet.FilterChain; | ||
import javax.servlet.ServletException; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
import java.util.Date; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
@Slf4j | ||
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter { | ||
private final AuthenticationManager authenticationManager; | ||
|
||
public CustomAuthenticationFilter(AuthenticationManager authenticationManager) { | ||
this.authenticationManager = authenticationManager; | ||
} | ||
|
||
@Override | ||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { | ||
String username = request.getParameter("username"); | ||
String password = request.getParameter("password"); | ||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); | ||
return authenticationManager.authenticate(authenticationToken); | ||
} | ||
|
||
@Override | ||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { | ||
User user = (User) authResult.getPrincipal(); | ||
Algorithm algorithm = Algorithm.HMAC256("secret".getBytes()); | ||
String access_token = JWT.create() | ||
.withSubject(user.getUsername()) | ||
.withExpiresAt(new Date(System.currentTimeMillis() + 100 * 60 * 1000)) | ||
.withIssuer(request.getRequestURL().toString()) | ||
.withClaim("roles", user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList())) | ||
.sign(algorithm); | ||
|
||
Map<String, String> token = new HashMap<>(); | ||
token.put("access_token", access_token); | ||
response.setContentType("application/json"); | ||
new ObjectMapper().writeValue(response.getOutputStream(), token); | ||
} | ||
} |
71 changes: 71 additions & 0 deletions
71
booking/src/main/java/org/example/filter/CustomAuthorizationFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package org.example.filter; | ||
|
||
import com.auth0.jwt.JWT; | ||
import com.auth0.jwt.JWTVerifier; | ||
import com.auth0.jwt.algorithms.Algorithm; | ||
import com.auth0.jwt.interfaces.DecodedJWT; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
import javax.servlet.FilterChain; | ||
import javax.servlet.ServletException; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import static java.util.Arrays.stream; | ||
import static org.springframework.http.HttpHeaders.*; | ||
import static org.springframework.http.HttpStatus.FORBIDDEN; | ||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; | ||
|
||
@Slf4j | ||
public class CustomAuthorizationFilter extends OncePerRequestFilter { | ||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { | ||
if (request.getServletPath().equals("/api/login")) { | ||
filterChain.doFilter(request, response); | ||
} else { | ||
String authorizationHeader = request.getHeader(AUTHORIZATION); | ||
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer")) { | ||
try { | ||
String token = authorizationHeader.substring("Bearer ".length()); | ||
Algorithm algorithm = Algorithm.HMAC256("secret".getBytes()); | ||
JWTVerifier verifier = JWT.require(algorithm).build(); | ||
DecodedJWT decodedJWT = verifier.verify(token); | ||
|
||
String username = decodedJWT.getSubject(); | ||
String[] roles = decodedJWT.getClaim("roles").asArray(String.class); | ||
|
||
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>(); | ||
stream(roles).forEach(role -> { | ||
authorities.add(new SimpleGrantedAuthority(role)); | ||
}); | ||
|
||
UsernamePasswordAuthenticationToken authenticationToken = | ||
new UsernamePasswordAuthenticationToken(username, null, authorities); | ||
SecurityContextHolder.getContext().setAuthentication(authenticationToken); | ||
|
||
filterChain.doFilter(request, response); | ||
} catch (Exception exception) { | ||
response.setHeader("Error", exception.getMessage()); | ||
response.setStatus(FORBIDDEN.value()); | ||
|
||
Map<String, String> errors = new HashMap<>(); | ||
errors.put("error_message", exception.getMessage()); | ||
response.setContentType(APPLICATION_JSON_VALUE); | ||
new ObjectMapper().writeValue(response.getOutputStream(), errors); | ||
} | ||
} else { | ||
filterChain.doFilter(request, response); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package org.example.model; | ||
|
||
import lombok.Data; | ||
|
||
@Data | ||
public class RoleToUserForm { | ||
private String username; | ||
private String roleName; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package org.example.model; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
import javax.persistence.*; | ||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
|
||
@Entity | ||
@Data | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
public class UserAccount { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.AUTO) | ||
private Long id; | ||
private String name; | ||
private String username; | ||
private String password; | ||
@ManyToMany(fetch = FetchType.EAGER) | ||
private Collection<UserRole> userRoles = new ArrayList<>(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package org.example.model; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.GeneratedValue; | ||
import javax.persistence.GenerationType; | ||
import javax.persistence.Id; | ||
|
||
@Entity | ||
@Data | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
public class UserRole { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.AUTO) | ||
private Long id; | ||
private String name; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.