
JWT ( JSON Web Token ) 개요
프로젝트에서 로그인 인증을 구현하면서 JWT에 알아보게 되었습니다.
웹 개발 및 보안 분야에서 자주 사용되는 JWT(Json Web Token)에 대해 자세히 알아보겠습니다.
이 기술은 웹 애플리케이션에서 사용자 인증 및 정보 교환을 보다 안전하게 하기 위한 강력한 수단 중 하나로 부상했습니다.
JWT의 기본 개념, 구조, 그리고 실제 활용 예시에 대해 알아보겠습니다.
JWT란?
JWT는 JSON Web Token의 약자로, JSON을 사용하여 정보를 안전하게 전송하기 위한 표준 방식 중 하나입니다.
JWT는 토큰 자체가 사용자 정보를 인코딩한 값이기 때문에 모든 정보를 가지고 있습니다. 따라서 서버의 세션 저장소에 정보를 저장할 필요가 없습니다.
주로 웹에서 사용되며, 클라이언트와 서버 간의 정보를 안전하게 전달하고 인증된 사용자를 식별하는 데 사용됩니다.
JWT는 어떻게 이루어져 있는가?
JWT는 점(.)으로 구분된 3개의 파트로 이루어져 있습니다.
첫 번째 파트는 Header, 두 번째 파트는 Payload, 세 번째 파트는 Signature 입니다.
각 파트는 Base64Url로 인코딩되어 있으며, 각각 "."으로 구분되어 있습니다.
- Header: 토큰의 타입과 해싱 알고리즘 정보가 들어 있습니다. 보통 JWT를 인코딩할 때 Base64Url로 인코딩되어 헤더 파트에 추가됩니다.
- Payload: 토큰에 포함될 정보, 클레임(claim)이라 불리는 키-값 쌍들이 포함됩니다. 예를 들면 사용자 ID, 권한 등이 있습니다. 마찬가지로 Base64Url로 인코딩되어 페이로드 파트에 추가됩니다.
- Signature: 토큰의 유효성을 확인하기 위한 서명입니다. 이 서명은 Header와 Payload를 인코딩한 후, 비밀 키를 이용하여 서명한 값입니다. 서명은 Base64Url로 인코딩되어 토큰 뒷부분에 추가됩니다.
JWT는 일반적으로 다음과 같습니다.
xxxxx.yyyyy.zzzzz
각각 분해해서 확인해 봅시다.
Header
header는 일반적으로 두 가지 부분으로 구성됩니다 :
- HMAC SHA256 또는 RSA 같은 서명 알고리즘
- 알고리즘 방식을 지정
- Signature를 해싱하기 위한 알고리즘을 지정
- Signature 및 토큰 검증에 사용
- ex) HS256(SHA256) 또는 RSA
- JWT 토큰 유형
# Header 예시
{
"alg": "HS256",
"typ": "JWT"
}
위와 같은 JSON은 JWT의 첫 번째 부분을 형성하도록 인코딩 되었습니다.
Payload
claims를 구성하는 토큰의 두 번째 부분입니다.
claims는 entity (일반적으로 사용자) 그리고 추가적인 데이터에 대한 내용입니다.
claims는 Registered claims, Public claims, Private claims 이렇게 3개의 유형이 있고, Json 형태로 다수의 정보를 넣을 수 있습니다.
- Registered claims (등록된 클레임)
- 토큰 정보를 표현하기 위해 이미 정해진 종류의 데이터
- 선택 사항
- 데이터 종류
- iss(issuer): 토큰 발급자
- sub(subject): 토큰 제목. unique한 값. 주로 사용자 이메일을 사용.
- aud(audience): 토큰 대상자
- exp(expiration): 토큰 만료 시간, NumericDate 형식. ex) 1480849147370
- nbf(not before): 토큰 활성 날짜, 이 날이 지나기 전의 토큰은 활성화되지 않음
- iat(issued at): 토큰 발급 시간, 토큰 발급 이후의 경과 시간을 알 수 있음
- jti(JWT ID): JWT 토큰 식별자, 중복 방지를 위해 사용하며, 일회용 토큰(Access Token) 등에 사용
- Public claims (공개 클레임)
- Private claims (비공개 클레임)
# Payload 예시
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
Signature
signature 부분을 생성하기 위해서는 인코드된 header와 인코드된 payload, secret, header에 지정된 알고리즘을 가져와서 서명해야 합니다.
예를 들어 만약 HMAC SHA256 알고리즘 사용을 원한다면 signature는 다음과 같이 작성됩니다. :
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
signature는 메시지가 변경되지 않았음을 검증하는데 사용되며, private key로 서명한 토큰의 경우 JWT의 발신자가 누구인지도 검증(확인)할 수 있습니다.
JSON Web Token들은 어떻게 작동할까?
인증 시, 사용자가 자격 증명을 사용하여 로그인에 성공했을 때 JSON Web Token이 리턴됩니다.
토큰들은 자격 증명이기 때문에 보안 문제를 방지하기 위해 세심한 주의를 기울여야 합니다. 일반적으로 토큰을 필요 이상으로 유지해서는 안됩니다. 민감한 세션 데이터를 보안에 취약한 브라우저 스토리지(예: Local Storage)에 저장해서는 안됩니다.
JWT의 활용 예시
- 인증(Authentication)
사용자가 로그인하면 서버는 사용자에게 JWT를 발급합니다. 클라이언트는 이 JWT를 이후의 모든 요청에 포함시켜 서버에 자신을 인증합니다.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
- 정보 교환
JWT는 클라이언트와 서버 간의 안전한 정보 교환을 가능케 합니다. 페이로드에 필요한 정보를 담아 서버 간에 주고받을 수 있습니다. - 세션 관리
JWT를 사용하면 서버는 세션 관리를 하지 않아도 됩니다. 토큰 자체가 모든 필요한 정보를 가지고 있기 때문입니다.
보안 고려사항
- 토큰의 유효 기간 설정: 토큰의 만료 시간을 적절히 설정하여 민감한 정보가 노출되는 것을 방지합니다.
- 알고리즘 선택: 헤더에 있는 알고리즘 정보를 이용하여 서명을 확인하므로, 안전한 알고리즘을 선택해야 합니다.
- HTTPS 사용: 토큰은 평문으로 전송되어서는 안 됩니다. 따라서 HTTPS를 사용하여 통신을 암호화하는 것이 중요합니다.
JWT는 간편하고 효과적인 방법으로 웹 애플리케이션의 보안을 강화하는 데 사용됩니다. 그러나 부적절한 사용이나 구현 실수로 인해 보안 문제가 발생할 수 있으므로 신중한 사용이 필요합니다.
Spring Security

- Client
- 사용자의 요청은 Security Filter Chain에 의해 수행됩니다.
- Security Filter Chain
- Security Filter A, B, ..., N :
Spring Security는 다양한 Filter Chain들로 구성되어 있습니다. Filter Chain들은 Request를 가로챈 후 일련의 절차(사용자 인증, CORS, CSRF 보호 등)를 처리합니다. - UsernamePasswordAuthenticationFilter는 사용자가 제출한 인증 정보를 처리합니다.
- Security Filter A, B, ..., N :
- Authentication Flow
- UsernamePassword Authentication Token :
UsernamePasswordAuthenticationFilter는 UsernamePasswordAuthenticationToken을 생성하여 AuthenticationManager에게 전달합니다. 이 토큰에는 사용자가 제출한 인증 정보가 포함되어 있습니다.
- UsernamePassword Authentication Token :
- AuthenticationManager / ProviderManager
- AuthenticationManager :
AuthenticationManager는 여러 AuthenticationProvider들을 이용해서 실제로 인증을 수행합니다.
- AuthenticationManager :
- Authentication Providers
- UserDetailsService / UserDetails
- UserDetailsService :
AuthenticationProvider는 UserDetailsService를 사용하여 사용자 정보를 가져옵니다. UserDetailsService는 사용자를 구분할 수 있는 아이디 또는 이메일을 받아 DB에서 사용자를 조회한 뒤 해당 사용자의 UserDetails를 반환합니다. - UserDetails에는 사용자 아이디, 비밀번호, 권한 등이 포함되어 있습니다.
- UserDetailsService :
- SecurityContext & JWT Authentication Filter
- Authentication Request/Response
- SecurityContext / SecurityContextHolder / SecurityContextHeader
- SecurityContext :
현재 사용자의 Authentication이 저장되어 있습니다. 애플리케이션은 SecurityContextHolder를 통해 현재 사용자의 권한을 확인하고, 인가 결정을 합니다.
- SecurityContext :
JWT 참고 코드 : https://github.com/yeen28/proj-authorization
Troubleshooting
Q: @PreAuthorize로 권한 체크를 하려고 하는데 어노테이션이 동작하지 않아요!
A: SecurityConfig에서 @EnableMethodSecurity(prePostEnabled = true) 어노테이션을 추가해야 합니다.
참고
- https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html
- https://jwt.io/introduction
- https://medium.com/@d971106b/%EC%82%BD%EC%A7%88-%EA%B8%B0%EB%A1%9D-1-auth-%EC%A0%81%EC%9A%A9-axios-default-header-%EC%B6%94%EA%B0%80-plugin-%EC%B6%94%EA%B0%80-a15d0beba330 - Auth 적용, axios default header 추가, plugin 추가
- https://chb2005.tistory.com/177 - 인증 실패 시 401 에러 출력 or 로그인 페이지로 redirect
- https://bibi6666667.tistory.com/311
- https://github.com/lms0806/SpringBoot-JWT/commit/ac5b3cdefd3c1f0958ea334985ac22dcb516642c#diff-7bc26be01d3e7c9c566f2a28dc1b5cd87dbdd5cb619184f46eb2bf223bf7825d
- https://genie247.tistory.com/entry/%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%84%B8%EC%85%98%EA%B4%80%EB%A6%AC-%EA%B5%AC%ED%98%84Interceptor-jwt-%ED%86%A0%ED%81%B0 - 로그인 세션관리 구현(Interceptor, jwt 토큰)
- https://velog.io/@eeeve/HttpOnly-Secure-Cookie
- https://blog.amigoscode.com/p/spring-security-architecture-explained
- https://sjh9708.tistory.com/170
'Study😜' 카테고리의 다른 글
[JAVA] 가비지 컬렉션 (0) | 2024.05.07 |
---|---|
OAuth 2.0 (Open Authorization) : 현대 웹과 API 인증의 표준 (0) | 2024.04.24 |
tmux (0) | 2024.01.07 |
package.json으로 협업하기! (0) | 2023.06.22 |
jenkins 설치 및 실행 가이드 (0) | 2023.06.07 |