🔑 JWT & 🛡️ Spring Security 정리
🧾 JWT (JSON Web Token)
💡 개념 요약
- 정의: 웹에서 사용하는 자바스크립트 기반의 특정한 데이터를 대신하는 증표
- 목적: 데이터를 직접 노출하지 않고 토큰(Token) 으로 대체하여 보안을 강화
- 사용처: 사용자 인증, 정보 보호, 세션 대체 등
- 알고리즘: 주로 SHA-256 기반의 HMAC 해시 알고리즘을 사용하여 비밀키 생성
🔍 핵심 개념
| 용어 | 설명 |
|---|
| 토큰(Token) | 사용자의 인증정보를 담은 암호화된 문자열 |
| 비밀키(Secret Key) | 토큰 서명 및 검증에 사용되는 키 (32자 이상 권장) |
| Claim | 토큰에 포함되는 데이터 (예: 사용자 ID, 권한 등) |
| Header | 토큰의 타입과 서명 알고리즘 정보 포함 |
| Payload | 사용자 데이터(Claim) 포함 영역 |
| Signature | Header + Payload를 비밀키로 서명한 값 |
⚙️ JWT 생성 / 검증 / 추출
1️⃣ 비밀키 생성
private final String secret = "";
private final Key secretKey = Keys.hmacShaKeyFor(secret.getBytes());
2️⃣ 토큰 생성
String token = Jwts.builder()
.claim(key, value)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 초))
.signWith(secretKey, SignatureAlgorithm.HS256)
.compact();
3️⃣ 토큰 검증
Jwts.parser()
.setSigningKey(secretKey)
.build()
.parseClaimsJws(token);
4️⃣ 토큰 추출
Jwts.parser()
.setSigningKey(secretKey)
.build()
.parseClaimsJws(token)
.getBody();
🍪 JWT + 쿠키 연동
- 회원정보를 기반으로 JWT를 생성한 후 쿠키에 저장할 수 있다.
Cookie cookie = new Cookie("loginUser", jwtService.generateToken(uid, urole));
| 항목 | 설명 |
|---|
| 쿠키 이름 | loginUser |
| 쿠키 값 | JWT 문자열 |
| 사용 목적 | 로그인 상태 유지 및 인증 정보 전달 |
🛡️ Spring Security
💬 개념 요약
- Spring Security는 HTTP 요청에 대한 권한 제어 및 인증/인가를 담당한다.
- SecurityConfig를 생성하여 요청 경로별 접근 권한을 커스텀할 수 있다.
⚙️ SecurityConfig 예시
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/user/info").hasAnyRole("USER", "ADMIN")
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/**").permitAll()
);
httpSecurity.csrf(csrf -> csrf.disable());
// 3️⃣ 세션 비활성화 (STATELESS → JWT 기반 인증)
httpSecurity.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
// 4️⃣ JWT 필터 등록 (UsernamePasswordAuthenticationFilter 전에 실행)
httpSecurity.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
🔐 주요 설정 요약
| 설정 항목 | 코드 | 설명 |
|---|
| 권한 설정 | .requestMatchers("/api/admin/**").hasRole("ADMIN") | 특정 경로에 대한 권한 제한 |
| 모든 권한 허용 | .requestMatchers("/**").permitAll() | 권한 없는 요청 허용 |
| CSRF 비활성화 | httpSecurity.csrf(csrf -> csrf.disable()) | POST/PUT 요청 허용 |
| 세션 끄기 | sessionCreationPolicy(SessionCreationPolicy.STATELESS) | 세션 대신 JWT 사용 |
| JWT 필터 추가 | .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class) | 사용자 정의 토큰 필터 등록 |
🔄 Spring Security + JWT 연동
🔧 필터 내부 동작 (쿠키 기반 인증)
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String token = null;
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
if (cookie.getName().equals("loginUser")) {
token = cookie.getValue();
}
}
}
if (token != null && jwtService.validateToken2(token)) {
String uid = jwtService.getUid(token);
String urole = jwtService.getUrole(token);
UsernamePasswordAuthenticationToken newAuthenticationToken =
new UsernamePasswordAuthenticationToken(uid, null,
List.of(new SimpleGrantedAuthority("ROLE_" + urole)));
SecurityContextHolder.getContext().setAuthentication(newAuthenticationToken);
}
filterChain.doFilter(request, response);
}
⚙️ 작동 순서 요약
| 단계 | 설명 |
|---|
| 1️⃣ | 쿠키에서 "loginUser" 토큰 추출 |
| 2️⃣ | jwtService.validateToken2()로 유효성 검증 |
| 3️⃣ | 토큰에서 uid, urole 추출 |
| 4️⃣ | UsernamePasswordAuthenticationToken 생성 후 SecurityContext에 등록 |
| 5️⃣ | 나머지 필터 체인 실행 |