This repository is a Software of Application with JAVA.
Using Spring Boot, JPA, JWT, Spring Security, Lombok, etc preferably.
Apply Gradle 7.1.1
Java version JDK-11
IntelliJ IDEA
Using PostgreSQL, H2Databse, MySQL,etc
Postman, Insomnia, Talend API Tester,etc
$ git clone https://github.com/DanielArturoAlejoAlvarez/SpringBoot-Gradle-7.1.1-SpringSecurity-JWT.git
[NAME APP]
Follow the following steps and you're good to go! Important:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
if (request.getServletPath().equals("/api/login") || request.getServletPath().equals("/api/token/refresh/**")) {
chain.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_key".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);
chain.doFilter(request,response);
}catch (Exception e) {
log.error("Error logging in: {}", e.getMessage());
response.setHeader("error", e.getMessage());
response.setStatus(FORBIDDEN.value());
Map<String,String> error = new HashMap<>();
error.put("error_message", e.getMessage());
response.setContentType(APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(response.getOutputStream(), error);
}
}else {
chain.doFilter(request,response);
}
}
}
@Entity
@Data
@AllArgsConstructor @NoArgsConstructor
@Table(name = "tbl_users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Column(unique = true, length = 128, nullable = false)
private String email;
@Column(unique = true)
private String username;
@Column(length = 100, nullable = false)
private String password;
@Column(length = 512)
private String avatar;
private Boolean status;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at")
private Date createdAt;
@ManyToMany(fetch = FetchType.LAZY)
@JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
private Collection<Role> roles = new ArrayList<>();
}
@PostMapping("/role/save")
public ResponseEntity<Role> saveRole(@RequestBody Role role) {
URI uri = URI.create(ServletUriComponentsBuilder.fromCurrentContextPath().path("/api/role/save").toString());
return ResponseEntity.created(uri).body(userService.saveRole(role));
}
@PostMapping("/role/addToUser")
public ResponseEntity<?> addRoleToUser(@RequestBody RoleToUserForm form) {
userService.addRoleToUser(form.getUsername(), form.getRoleName());
return ResponseEntity.ok().build();
}
@GetMapping("/token/refresh")
public void refreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
String authorizationHeader = request.getHeader(AUTHORIZATION);
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
try {
String refresh_token = authorizationHeader.substring("Bearer ".length());
Algorithm algorithm = Algorithm.HMAC256("secret_key".getBytes());
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT decodedJWT = verifier.verify(refresh_token);
String username = decodedJWT.getSubject();
User user = userService.getUser(username);
String access_token = JWT.create()
.withSubject(user.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + 10 * 60 * 1000))
.withIssuer(request.getRequestURI().toString())
.withClaim("roles", user.getRoles().stream().map(Role::getName).collect(Collectors.toList()))
.sign(algorithm);
Map<String,String> tokens = new HashMap<>();
tokens.put("access_token", access_token);
tokens.put("refresh_token", refresh_token);
response.setContentType(APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(response.getOutputStream(), tokens);
}catch (Exception e) {
log.error("Error logging in: {}", e.getMessage());
response.setHeader("error", e.getMessage());
response.setStatus(FORBIDDEN.value());
Map<String,String> error = new HashMap<>();
error.put("error_message", e.getMessage());
response.setContentType(APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(response.getOutputStream(), error);
}
}else {
throw new RuntimeException("Refresh token is missing");
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
CustomAuthenticationFilter customAuthenticationFilter = new CustomAuthenticationFilter(authenticationManagerBean());
customAuthenticationFilter.setFilterProcessesUrl("/api/login");
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(STATELESS);
http.authorizeRequests().antMatchers("/api/login/**", "/api/token/refresh/**").permitAll();
http.authorizeRequests().antMatchers(GET, "/api/user/**").hasAnyAuthority("ROLE_USER");
http.authorizeRequests().antMatchers(POST, "/api/user/save/**").hasAnyAuthority("ROLE_ADMIN");
http.authorizeRequests().anyRequest().authenticated();
http.addFilter(customAuthenticationFilter);
http.addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepo.findByUsername(username);
if (user == null) {
log.error("User not found in the database");
throw new UsernameNotFoundException("User not found in the database");
}else {
log.info("User found in the database: {}", username);
}
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
user.getRoles().forEach(role -> {
authorities.add(new SimpleGrantedAuthority(role.getName()));
});
return new org.springframework.security.core.userdetails
.User(user.getUsername(),user.getPassword(),authorities);
}
Bug reports and pull requests are welcome on GitHub at https://github.com/DanielArturoAlejoAlvarez/SpringBoot-Gradle-7.1.1-SpringSecurity-JWT. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.