Skip to content

Commit 82603a3

Browse files
committed
[feat] : JWT 인증 필터를 구현하여 사용자 ID를 SecurityContext에 설정 #8
1 parent 3f12e6b commit 82603a3

File tree

5 files changed

+130
-2
lines changed

5 files changed

+130
-2
lines changed

src/main/java/org/dfbf/soundlink/domain/user/controller/UserController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.dfbf.soundlink.domain.user.dto.request.UserUpdateDto;
1212
import org.dfbf.soundlink.domain.user.service.UserService;
1313
import org.dfbf.soundlink.global.exception.ResponseResult;
14+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
1415
import org.springframework.web.bind.annotation.*;
1516

1617
@RestController
@@ -36,7 +37,7 @@ public ResponseResult checkNickName(@RequestParam String nickName){
3637

3738
@GetMapping
3839
@Operation(summary = "유저 조회", description = "유저 조회 API")
39-
public ResponseResult getUser(/*@AuthenticationPrincipal id: Int*/) { return userService.getUser(1L); }
40+
public ResponseResult getUser(@AuthenticationPrincipal Long id) { return userService.getUser(id); }
4041

4142
@PutMapping
4243
@Operation(summary = "유저 수정", description = "유저 수정 API")
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package org.dfbf.soundlink.global.auth;
2+
3+
import org.springframework.security.core.GrantedAuthority;
4+
import org.springframework.security.core.userdetails.UserDetails;
5+
6+
import java.util.Collection;
7+
import java.util.List;
8+
9+
public class CustomUserDetails implements UserDetails{
10+
private final Long userId;
11+
12+
public CustomUserDetails(Long userId) {
13+
if (userId == null) {
14+
throw new IllegalArgumentException("userId cannot be null");
15+
}
16+
this.userId = userId;
17+
}
18+
19+
public Long getUserId() {
20+
return userId;
21+
}
22+
23+
24+
@Override
25+
public Collection<? extends GrantedAuthority> getAuthorities() {
26+
return List.of(); //사용자의 권한 정보 반환
27+
}
28+
29+
@Override
30+
public String getPassword() {
31+
return null;
32+
}
33+
34+
@Override
35+
public String getUsername() {
36+
return String.valueOf(userId);//로그인할때 ID
37+
}
38+
39+
@Override
40+
public boolean isAccountNonExpired() {
41+
return true; //계정 만료 여부(만료 x)
42+
}
43+
44+
@Override
45+
public boolean isAccountNonLocked() {
46+
return true; //계정이 잠겨있는지 확인.
47+
}
48+
49+
@Override
50+
public boolean isCredentialsNonExpired() {
51+
return true; //비밀번호 유효기간 확인
52+
}
53+
54+
@Override
55+
public boolean isEnabled() {
56+
return true; //계정활성화 여부 확인
57+
}
58+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.dfbf.soundlink.global.auth;
2+
3+
import jakarta.servlet.FilterChain;
4+
import jakarta.servlet.ServletException;
5+
import jakarta.servlet.http.HttpServletRequest;
6+
import jakarta.servlet.http.HttpServletResponse;
7+
import lombok.RequiredArgsConstructor;
8+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
9+
import org.springframework.security.core.context.SecurityContextHolder;
10+
import org.springframework.web.filter.OncePerRequestFilter;
11+
12+
import java.io.IOException;
13+
14+
@RequiredArgsConstructor
15+
public class JwtAuthenticationFilter extends OncePerRequestFilter {
16+
private final JwtProvider jwtProvider;
17+
18+
@Override
19+
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
20+
String accessToken = jwtProvider.resolveAccessToken(request); //1.Access Token 추출
21+
22+
if(accessToken !=null && jwtProvider.validateToken(accessToken)) { //2.유효성 검사
23+
this.setAuthentication(accessToken); //3.유저정보 저장
24+
}
25+
filterChain.doFilter(request, response); //필터 체인 진행(전달)
26+
}
27+
28+
//유저정보 저장
29+
public void setAuthentication(String token) {
30+
Long userId = jwtProvider.getUserId(token); //userId 추출
31+
32+
// 로그 추가
33+
System.out.println("Extracted User ID: " + userId);
34+
35+
if (userId == null) {
36+
throw new IllegalArgumentException("userId cannot be null");
37+
}
38+
39+
CustomUserDetails userDetails = new CustomUserDetails(userId);
40+
41+
// 로그 추가
42+
System.out.println("Created CustomUserDetails: " + userDetails);
43+
44+
// 인증토큰 생성
45+
UsernamePasswordAuthenticationToken authentication =
46+
new UsernamePasswordAuthenticationToken(userId, null, userDetails.getAuthorities());
47+
48+
// 인증정보 설정
49+
System.out.println("Setting authentication with user ID: " + userId); // 로그 추가
50+
SecurityContextHolder.getContext().setAuthentication(authentication);
51+
}
52+
53+
}

src/main/java/org/dfbf/soundlink/global/auth/JwtProvider.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,14 @@ public String resolveRefreshToken(HttpServletRequest request) {
9898
return null;
9999
}
100100

101+
// 토큰에서 id 반환
102+
public Long getUserId(String token){
103+
return Long.parseLong(Jwts.parserBuilder()
104+
.setSigningKey(SECRET_KEY)
105+
.build()
106+
.parseClaimsJws(token)
107+
.getBody()
108+
.getSubject());
109+
}
110+
101111
}

src/main/java/org/dfbf/soundlink/global/config/SecurityConfig.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.dfbf.soundlink.global.config;
22

33
import lombok.RequiredArgsConstructor;
4+
import org.dfbf.soundlink.global.auth.JwtAuthenticationFilter;
5+
import org.dfbf.soundlink.global.auth.JwtProvider;
46
import org.springframework.context.annotation.Bean;
57
import org.springframework.context.annotation.Configuration;
68
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -15,6 +17,8 @@
1517
@EnableWebSecurity
1618
@RequiredArgsConstructor
1719
public class SecurityConfig {
20+
private final JwtProvider jwtProvider;
21+
1822
@Bean
1923
public BCryptPasswordEncoder passwordEncoder() {
2024
return new BCryptPasswordEncoder();
@@ -31,7 +35,9 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
3135
// .requestMatchers("/").permitAll()
3236
// .anyRequest().authenticated()
3337
.anyRequest().permitAll()
34-
);
38+
)
39+
// JwtAuthenticationFilter 추가
40+
.addFilterBefore(new JwtAuthenticationFilter(jwtProvider), UsernamePasswordAuthenticationFilter.class);
3541

3642
return http.build();
3743
}

0 commit comments

Comments
 (0)