토큰 검증
발행: (2025년 12월 15일 오전 01:42 GMT+9)
4 min read
원문: Dev.to
Source: Dev.to
개요
JWT를 검증하는 과정은 다음과 같습니다:
- 토큰 문자열을 파싱합니다.
- 헤더와 페이로드를 디코딩합니다.
- 적절한 비밀키/키를 사용해 서명을 검증합니다.
- 페이로드 데이터를 이용해 커스텀
Claims구조체를 채웁니다. - 토큰이 유효하면 클레임을 반환하고, 그렇지 않으면 오류를 반환합니다.
Claims 구조체
type Claims struct {
UserID string `json:"user_id"`
jwt.StandardClaims
}
Claims 구조체는 jwt.StandardClaims를 임베드하고, 사용자 정의 UserID 필드를 추가합니다.
비밀 키
secretKey := GetJWTKey()
GetJWTKey()는 JWT 서명 및 검증에 사용되는 전역 비밀 키를 반환합니다.- 이 예제에서는 알고리즘이 HS256이므로 키는
[]byte형태입니다. - 동일한 키가 모든 사용자에게 사용됩니다.
토큰 파싱
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return secretKey, nil
})
ParseWithClaims 작동 방식
- 토큰을 세 부분(헤더, 페이로드, 서명)으로 분리합니다.
- 헤더와 페이로드를 임시
jwt.Token구조체에 디코딩합니다. - 키 함수(위의 익명 함수)를 호출해 검증 키(
secretKey)를 얻습니다. - 다음을 사용해 예상 서명을 다시 계산합니다:
- 디코딩된 헤더와 페이로드
- 비밀 키
token.Method에 지정된 알고리즘(예: HS256)
- 재계산된 서명을 토큰에 포함된 서명과 비교합니다.
- 일치하면
token.Valid = true로 설정하고, 제공된Claims구조체에 페이로드 데이터를 채웁니다.
내부 Token 표현
type Token struct {
Raw string // 원본 토큰 문자열
Method jwt.SigningMethod // 서명 알고리즘(예: HS256)
Header map[string]interface{} // 헤더 필드(예: "alg")
Claims jwt.Claims // 클레임(&Claims{} 로 채워짐)
Signature string // Base64‑인코딩된 서명 부분
Valid bool // 서명 및 클레임 검증 결과
}
파싱된 클레임 사용하기
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
return claims, nil
}
- 일반적인
token.Claims를 구체적인*Claims구조체로 타입 어설션합니다. - 토큰이 유효하면 함수는 채워진
claims를 반환하고, 그렇지 않으면 오류를 반환합니다.
TL;DR 흐름
jwt.ParseWithClaims가tokenString을 받습니다.- 토큰을 → 헤더, 페이로드, 서명으로 분리합니다.
- 헤더와 페이로드를 임시
jwt.Token에 디코딩합니다. - 키 함수를 호출 →
secretKey를 반환합니다. secretKey와 헤더에 명시된 알고리즘을 사용해 서명을 다시 계산합니다.- 재계산된 서명을 토큰의 서명과 비교합니다.
- 일치 → 토큰이 유효하고
token.Valid = true가 됩니다. - 불일치 → 토큰이 무효입니다.
- 일치 → 토큰이 유효하고
- 제공된
&Claims{}구조체에 페이로드 데이터를 채웁니다. - 호출자에게 클레임(또는 오류)을 반환합니다.