728x90
1. JWT(Json Web Token)
JWT(Json Web Token)는 서버와 클라이언트 간 인증 정보를 안전하게 전달하기 위한 토큰 기반 인증 방식으로,
세션 상태를 유지하지 않고도 인증과 권한 부여를 구현할 수 있어 마이크로서비스, REST API, 모바일 앱에서 널리 사용됩니다.
그러나 잘못 구현된 JWT는 인증 우회, 토큰 위조, 탈취 등의 심각한 보안 문제로 이어질 수 있으므로, 정확한 구조 이해와 보안 Best Practice 적용이 필수입니다.
2. JWT 기본 구조 이해
JWT는 세 부분으로 구성되며 . 으로 구분됩니다:
Header.Payload.Signature
📦 구성 설명:
구성 요소 | 설명 |
Header | 토큰 타입(JWT)과 서명 알고리즘 정보 |
Payload | 사용자 정보 및 권한, 만료 시간 등 클레임 포함 |
Signature | 비밀 키를 이용한 서명, 데이터 위·변조 방지 |
3. 취약한 JWT 인증 구현 예제
(1) 취약 코드: 검증 없이 디코딩
String token = request.getHeader("Authorization").substring(7);
String[] split = token.split("\\.");
String payload = new String(Base64.getDecoder().decode(split[1]));
System.out.println("Payload: " + payload); // ❌ 검증 없이 디코딩만 수행
✅ 문제점:
- 서명(Signature) 검증 누락 → 공격자가 Payload를 수정한 가짜 토큰을 제출해도 무효화되지 않음
- 알고리즘을 none으로 설정한 토큰도 통과 가능
4. 안전한 JWT 인증 구현 예제 (Java + jjwt 라이브러리)
(1) 토큰 생성
String jwt = Jwts.builder()
.setSubject("user@example.com")
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1시간 유효
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
(2) 토큰 검증
Claims claims = Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
String username = claims.getSubject();
✅ 보안 강화 포인트:
- 서명(Signature) 검증 필수
- 유효 기간(exp) 반드시 설정
- 기밀 키는 안전하게 관리 (예: 환경변수, Vault 등)
5. JWT 인증 보안 강화 Best Practices
Best Practice | 설명 |
HS256 → RS256 사용 고려 | 대칭키 방식보다 공개/비공개 키 기반 비대칭 알고리즘이 더 안전 |
토큰 만료 시간 짧게 설정 | 일반적으로 15분~1시간 이내 권장 |
Refresh Token 전략 도입 | Access Token이 만료된 후 자동 재발급 |
Secure, HttpOnly 쿠키 사용 | 토큰을 스토리지 대신 쿠키에 저장해 XSS, CSRF 방어 |
토큰 블랙리스트 적용 | 사용자 로그아웃 또는 탈퇴 시 토큰 무효화 필요 |
권한 정보는 최소한으로 | Payload에 민감한 정보 포함 금지 (예: 비밀번호, 주민번호 등) |
6. Spring Security + JWT 적용 예시
(1) JWT 필터 구현
public class JwtFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String token = resolveToken(request);
if (token != null && validateToken(token)) {
Authentication auth = getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
filterChain.doFilter(request, response);
}
}
(2) 필터 등록
http.addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class);
✅ Spring Security와 연계하면 Role 기반 접근 제어, 필터 체인 통합 관리 가능7. 결론
JWT는 편리하지만 정확한 검증과 안전한 설계 없이는 보안상 매우 위험할 수 있습니다.
OWASP에서도 강조하듯, 토큰 유효성 검증, 서명 알고리즘 강제화, 만료 전략 등 다층적 보안 기법을 적용하는 것이 필수입니다.
✅ 다음 포스팅:
다음 글에서는 "Spring Security 기반 권한 제어 실전 가이드 (RBAC 중심)"을 분석합니다.
728x90
'시큐어코딩 > JAVA' 카테고리의 다른 글
(시큐어코딩) Spring Security 기반의 JWT 통합 전략 (0) | 2025.04.03 |
---|---|
(시큐어코딩) Spring Security 기반 권한 제어 실전 가이드 – RBAC 중심 (0) | 2025.04.03 |
(시큐어코딩) Java에서 OWASP Top 10 기반의 보안 인증(Authentication) 강화 기법 (0) | 2025.03.20 |
(시큐어코딩) Java에서 HTTP 응답 헤더 보안 설정(Content Security Policy, HSTS, X-Frame-Options) (0) | 2025.03.20 |
(시큐어코딩) Java에서 CSRF(크로스 사이트 요청 위조) 보안취약점 공격 방어 전략 (0) | 2025.03.18 |