Skip to content

Commit 337c06e

Browse files
committed
Add JWT authentication
1 parent c97cae2 commit 337c06e

File tree

6 files changed

+230
-22
lines changed

6 files changed

+230
-22
lines changed

pom.xml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,23 @@
8282
<artifactId>gson</artifactId>
8383
<version>2.10.1</version>
8484
</dependency>
85-
86-
85+
<dependency>
86+
<groupId>io.jsonwebtoken</groupId>
87+
<artifactId>jjwt-api</artifactId>
88+
<version>0.11.5</version> <!-- Hoặc phiên bản mới nhất -->
89+
</dependency>
90+
<dependency>
91+
<groupId>io.jsonwebtoken</groupId>
92+
<artifactId>jjwt-impl</artifactId>
93+
<version>0.11.5</version>
94+
<scope>runtime</scope>
95+
</dependency>
96+
<dependency>
97+
<groupId>io.jsonwebtoken</groupId>
98+
<artifactId>jjwt-jackson</artifactId> <!-- Hoặc jjwt-gson nếu bạn dùng Gson -->
99+
<version>0.11.5</version>
100+
<scope>runtime</scope>
101+
</dependency>
87102

88103

89104

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.programming.userService.config;
2+
3+
import com.programming.userService.util.JwtUtil;
4+
import org.springframework.beans.factory.annotation.Autowired;
5+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
6+
import org.springframework.security.core.context.SecurityContextHolder;
7+
import org.springframework.security.core.userdetails.UserDetails;
8+
import org.springframework.security.core.userdetails.UserDetailsService;
9+
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
10+
import org.springframework.stereotype.Component;
11+
import org.springframework.web.filter.OncePerRequestFilter;
12+
import jakarta.servlet.FilterChain;
13+
import jakarta.servlet.ServletException;
14+
import jakarta.servlet.http.HttpServletRequest;
15+
import jakarta.servlet.http.HttpServletResponse;
16+
17+
import java.io.IOException;
18+
19+
@Component
20+
public class JwtRequestFilter extends OncePerRequestFilter {
21+
22+
@Autowired
23+
private UserDetailsService userDetailsService;
24+
25+
@Autowired
26+
private JwtUtil jwtUtil;
27+
28+
@Override
29+
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
30+
throws ServletException, IOException {
31+
32+
final String authorizationHeader = request.getHeader("Authorization");
33+
34+
String username = null;
35+
String jwt = null;
36+
37+
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
38+
jwt = authorizationHeader.substring(7);
39+
username = jwtUtil.extractUsername(jwt);
40+
}
41+
42+
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
43+
44+
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
45+
46+
if (jwtUtil.validateToken(jwt, userDetails)) {
47+
48+
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
49+
userDetails, null, userDetails.getAuthorities());
50+
usernamePasswordAuthenticationToken
51+
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
52+
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
53+
}
54+
}
55+
chain.doFilter(request, response);
56+
}
57+
}

src/main/java/com/programming/userService/config/SecurityConfig.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.springframework.security.crypto.password.PasswordEncoder;
1313
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
1414
import org.springframework.security.web.SecurityFilterChain;
15+
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
1516

1617
import java.util.ArrayList;
1718
import java.util.Collection;
@@ -21,25 +22,26 @@ public class SecurityConfig {
2122

2223
@Bean
2324
public SecurityFilterChain defaultFilterChain(HttpSecurity httpSecurity) throws Exception {
25+
JwtRequestFilter jwtRequestFilter = new JwtRequestFilter();
2426
return httpSecurity
2527
.csrf(csrf -> csrf.disable())
26-
.authorizeHttpRequests(auth -> auth.requestMatchers("/register", "/error").permitAll()
27-
.requestMatchers("/listUser").permitAll()
28-
.requestMatchers("/video/upload").permitAll()
29-
.requestMatchers("/video/list").permitAll()
30-
.requestMatchers("/file/upload").permitAll()
31-
.requestMatchers("/file/list").permitAll()
32-
.requestMatchers("/file/downloadZipFile").permitAll()
33-
.requestMatchers("/comments/upload").permitAll()
34-
.requestMatchers("/comments/**").permitAll()
35-
.requestMatchers("/video/**").permitAll()
36-
.requestMatchers("/login2").permitAll()
37-
.requestMatchers("/listUserbyId/**").permitAll()
38-
.requestMatchers("/updateProfile/**").permitAll()
39-
.requestMatchers("/send-verification-email").permitAll()
40-
.requestMatchers("/hello-world").permitAll()
41-
.requestMatchers("/**").permitAll()
28+
.authorizeHttpRequests(auth -> auth.requestMatchers("/user/register", "/user/error").permitAll()
29+
// .requestMatchers("/listUser").permitAll()
30+
.requestMatchers("/user/login2").permitAll()
31+
.requestMatchers("/user/login3").permitAll()
32+
.requestMatchers("/user/listUserbyId/**").permitAll()
33+
.requestMatchers("/user/hello-world").permitAll()
34+
.requestMatchers("/user/send-verification-email").permitAll()
35+
.requestMatchers("/user/logout").permitAll()
36+
.requestMatchers("/user/listUserbyUsername").permitAll()
37+
.requestMatchers("/user/listUserbyId/**").permitAll()
38+
.requestMatchers("/user/updateProfile/**").permitAll()
39+
.requestMatchers("/user/changePassword/**").permitAll()
40+
.requestMatchers("/user/listUser").permitAll()
41+
42+
.requestMatchers("/user/").authenticated()
4243
.anyRequest().authenticated())
44+
.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)
4345
.httpBasic(Customizer.withDefaults())
4446
.formLogin(Customizer.withDefaults())
4547
.build();

src/main/java/com/programming/userService/controller/UserController.java

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,20 @@
3030
import java.util.Date;
3131
import java.util.HashMap;
3232
import java.util.Map;
33-
33+
import com.programming.userService.util.JwtUtil;
34+
import com.programming.userService.entity.CustomUserDetails;
35+
import com.programming.userService.entity.AuthUser;
3436
@RestController
3537
@AllArgsConstructor
3638
@RequestMapping("/user")
3739
public class UserController {
3840

39-
private final AuthUserRepository userRepository;
41+
private final AuthUserRepository userRepository;
4042
private final PasswordEncoder passwordEncoder;
43+
44+
@Autowired
45+
private JwtUtil jwtUtil;
46+
4147
@Autowired
4248
private JavaMailSender javaMailSender;
4349

@@ -89,13 +95,35 @@ public ResponseEntity registerUser(@RequestBody AuthUser user) {
8995
}
9096

9197
private byte[] getDefaultAvatar() throws IOException {
92-
String defaultAvatarPath = "/app/images/avatar.png"; // Path inside the Docker container
98+
// String defaultAvatarPath = "/app/images/avatar.png"; // Path inside the Docker container
99+
String defaultAvatarPath = "src/main/java/com/programming/userService/images/avatar.png"; // Path on local machine
93100
Path path = Paths.get(defaultAvatarPath);
94101
return Files.readAllBytes(path);
95102
}
96103

104+
@PostMapping("/login3")
105+
public ResponseEntity<?> loginUser3(@RequestBody AuthUser user) {
106+
try {
107+
AuthUser userFromDb = userRepository.findByUsername(user.getUsername())
108+
.orElseThrow(() -> new Exception("User not found"));
109+
110+
if (passwordEncoder.matches(user.getPassword(), userFromDb.getPassword())) {
111+
// Chuyển AuthUser sang CustomUserDetails
112+
CustomUserDetails userDetails = new CustomUserDetails(userFromDb);
113+
String token = jwtUtil.generateToken(userDetails); // Tạo JWT token với UserDetails
114+
Map<String, String> response = new HashMap<>();
115+
response.put("token", token);
116+
return ResponseEntity.ok(response);
117+
} else {
118+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid credentials");
119+
}
120+
} catch (Exception e) {
121+
return ResponseEntity.internalServerError().body(e.getMessage());
122+
}
123+
}
124+
97125
@PostMapping("/login2")
98-
public ResponseEntity loginUser(@RequestBody AuthUser user) {
126+
public ResponseEntity loginUser2(@RequestBody AuthUser user) {
99127
try {
100128
AuthUser userFromDb = userRepository.findByUsername(user.getUsername())
101129
.orElseThrow(() -> new Exception("User not found"));
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.programming.userService.entity;
2+
3+
import org.springframework.security.core.GrantedAuthority;
4+
import org.springframework.security.core.userdetails.UserDetails;
5+
import java.util.Collection;
6+
import java.util.Collections;
7+
8+
public class CustomUserDetails implements UserDetails {
9+
10+
private final AuthUser authUser;
11+
12+
public CustomUserDetails(AuthUser authUser) {
13+
this.authUser = authUser;
14+
}
15+
16+
@Override
17+
public Collection<? extends GrantedAuthority> getAuthorities() {
18+
return Collections.emptyList(); // Thêm danh sách quyền nếu cần thiết
19+
}
20+
21+
@Override
22+
public String getPassword() {
23+
return authUser.getPassword();
24+
}
25+
26+
@Override
27+
public String getUsername() {
28+
return authUser.getUsername();
29+
}
30+
31+
@Override
32+
public boolean isAccountNonExpired() {
33+
return true;
34+
}
35+
36+
@Override
37+
public boolean isAccountNonLocked() {
38+
return true;
39+
}
40+
41+
@Override
42+
public boolean isCredentialsNonExpired() {
43+
return true;
44+
}
45+
46+
@Override
47+
public boolean isEnabled() {
48+
return true;
49+
}
50+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.programming.userService.util;
2+
3+
import io.jsonwebtoken.Claims;
4+
import io.jsonwebtoken.Jwts;
5+
import io.jsonwebtoken.SignatureAlgorithm;
6+
import org.springframework.security.core.userdetails.UserDetails;
7+
import org.springframework.stereotype.Service;
8+
9+
import java.util.Date;
10+
import java.util.HashMap;
11+
import java.util.Map;
12+
import java.util.function.Function;
13+
14+
15+
@Service
16+
public class JwtUtil {
17+
private String SECRET_KEY = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; // Thay đổi SECRET_KEY với giá trị bảo mật của bạn
18+
19+
public String extractUsername(String token) {
20+
return extractClaim(token, Claims::getSubject);
21+
}
22+
23+
public Date extractExpiration(String token) {
24+
return extractClaim(token, Claims::getExpiration);
25+
}
26+
27+
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
28+
final Claims claims = extractAllClaims(token);
29+
return claimsResolver.apply(claims);
30+
}
31+
32+
private Claims extractAllClaims(String token) {
33+
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
34+
}
35+
36+
private Boolean isTokenExpired(String token) {
37+
return extractExpiration(token).before(new Date());
38+
}
39+
40+
public String generateToken(UserDetails userDetails) {
41+
Map<String, Object> claims = new HashMap<>();
42+
return createToken(claims, userDetails.getUsername());
43+
}
44+
45+
private String createToken(Map<String, Object> claims, String subject) {
46+
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
47+
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // Token có hiệu lực trong 10
48+
// giờ
49+
.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
50+
}
51+
52+
public Boolean validateToken(String token, UserDetails userDetails) {
53+
final String username = extractUsername(token);
54+
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
55+
}
56+
}

0 commit comments

Comments
 (0)