[React] JWT토큰

6718 단어 ReactwebReact

로그인을 하고 유저의 요청과 응답 처리를 안전하게 주고 받기위해서 JWT 토큰을 사용하였다. 프론트엔드 작업을 할 때 서버에서 넘겨주는 토큰을 localstorage에 저장하고 인증여부를 체크했지만 좀더 이론을 알기위해 글을 작성하기로 했다.

JWT 토큰이란? (Json Web Token)

  • Json 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token이다. JWT는 토큰 자체를 정보로 사용하는 Self-Contained 방식으로 정보를 안전하게 전달한다. 주로 회원 인증이나 정보 전달에 사용되는 JWT는 아래의 로직을 따라서 처리된다.

출처: https://mangkyu.tistory.com/56 [MangKyu's Diary]

언제 사용하는가

  1. 로그인
    • 사용자 로그인 -> 서버가 해당 유저의 토큰을 유저에게 전달 (JWT) -> 유저가 유청을 할때 토큰을 포함해서 전달 -> 서버는 해당 토큰일 권한이 있는지 유효하고 인증이 되었는지 확인하고 작업을 진행
    • 서버는 유저의 세션을 유지할 필요가 없다. 유저가 보낸 토큰만 확인하면 된다. 서버의 자원을 아낄수 있다.
  2. 정보교류
    • JWT는 두 개체 사이에서 안정성있게 정보를 교환하기에 좋은 방법이다. 그 이유는, 정보가 sign 이 되어있기 때문에 정보를 보낸이가 바뀌진 않았는지, 또 정보가 도중에 조작되지는 않았는지 검증할 수 있다.

JWT 구조

  • Header, Payload, Signature의 3부분으로 이루어져 있다. Json 형태인 각 부분은 Base64로 인코딩 되어 표현된다. 각 부분을 이어주기 위해 .구분자를 반환한다.
  • Base64는 암호화된 문자열이 아니고, 같은 문자열에 대해 항상 같은 문자열을 반환한다.
  1. Header
  • Header 는 두가지의 정보를 지니고 있습니다.

  • typ: 토큰의 타입을 지정합니다. ex)JWT

  • alg: 해싱 알고리즘을 지정합니다. 해싱 알고리즘으로는 보통 HMAC SHA256 혹은 RSA 가 사용되며, 이 알고리즘은, 토큰을 검증 할 때 사용되는 signature 부분에서 사용됩니다.

{ 
 "alg": "HS256",
 "typ": JWT
}
  1. Payload
  • Payload 부분에는 토큰에 담을 정보가 들어있습니다. 여기에 담는 정보의 한 ‘조각’ 을 클레임(Claim) 이라고 부르고, 이는 Json(Key/Value) 형태의 한 쌍으로 이뤄져있습니다. 토큰에는 여러개의 클레임들을 넣을 수 있습니다.

  • 클레임 의 종류는 다음과 같이 크게 세 분류로 나뉘어져있습니다:

    등록된 (registered) 클레임
    공개 (public) 클레임
    비공개 (private) 클레임

    1) 등록된 (registered) 클레임
    iss: 토큰 발급자 (issuer)
    sub: 토큰 제목 (subject)
    aud: 토큰 대상자 (audience)
    exp: 토큰의 만료시간 (expiraton), 시간은 NumericDate 형식으로 되어있어야 하며 (예: 1480849147370) 언제나 현재 시간보다 이후로 설정되어있어야합니다.
    nbf: Not Before 를 의미하며, 토큰의 활성 날짜와 비슷한 개념입니다. 여기에도 NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.
    iat: 토큰이 발급된 시간 (issued at), 이 값을 사용하여 토큰의 age 가 얼마나 되었는지 판단 할 수 있습니다.
    jti: JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용됩니다. 일회용 토큰에 사용하면 유용합니다.
    2) 공개(public)클레임
    공개 클레임들은 충돌이 방지된 (collision-resistant) 이름을 가지고 있어야 합니다. 충돌을 방지하기 위해서는, 클레임 이름을 URI 형식으로 짓습니다.

    {
       "https://velopert.com/jwt_claims/is_admin": true
    }

    3) 비공개(private)클레임
    등록된 클레임도아니고, 공개된 클레임들도 아닙니다. 양 측간에 (보통 클라이언트 <->서버) 협의하에 사용되는 클레임 이름들입니다. 공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있으니 사용할때에 유의해야합니다.

    {
    "username": "velopert"
    }

    Payload 예시 정리

    {
      "iss": "velopert.com",
      "exp": "1485270000000",
      "https://velopert.com/jwt_claims/is_admin": true,
      "userId": "11028373727102",
      "username": "velopert"
    }

    2개의 등록된 클레임, 1개의 공개 클레임, 2개의 비공개 클레임

  1. Signature
  • 서명(Signature)은 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드이다. 서명(Signature)은 위에서 만든 헤더(Header)와 페이로드(Payload)의 값을 각각 BASE64로 인코딩하고, 인코딩한 값을 비밀 키를 이용해 헤더(Header)에서 정의한 알고리즘으로 해싱을 하고, 이 값을 다시 BASE64로 인코딩하여 생성한다.

JWT토큰 장단점

JWT의 장점

  • JWT 의 주요한 이점은 사용자 인증에 필요한 모든 정보는 토큰 자체에 포함하기 때문에 별도의 인증 저장소가 필요 없습니다.
  • 쿠키를 전달하지 않아도 되므로 쿠키를 사용함으로써 발생하는 취약점이 사라집니다.
  • URL 파라미터와 헤더로 사용
  • 트래픽 대한 부담이 낮음
  • REST 서비스로 제공 가능
  • 내장된 만료
  • 독립적인 JWT

JWT의 단점

  • Self-contained: 토큰 자체에 정보를 담고 있으므로 양날의 검이 될 수 있습니다.
  • 토큰 길이: 토큰의 페이로드(Payload)에 3종류의 클레임을 저장하기 때문에, 정보가 많아질수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있습니다.
  • Payload 인코딩: 페이로드(Payload) 자체는 암호화 된 것이 아니라, BASE64로 인코딩 된 것입니다. 중간에 Payload를 탈취하여 디코딩하면 데이터를 볼 수 있으므로, JWE로 암호화하거나 Payload에 중요 데이터를 넣지 않아야 합니다.
  • Stateless: JWT는 상태를 저장하지 않기 때문에 한번 만들어지면 제어가 불가능합니다. 즉, 토큰을 임의로 삭제하는 것이 불가능하므로 토큰 만료 시간을 꼭 넣어주어야 합니다.
  • Tore Token: 토큰은 클라이언트 측에서 관리해야 하기 때문에, 토큰을 저장해야 합니다.

참고)
https://velopert.com/2389
https://velog.io/@dnjscksdn98/JWT-JSON-Web-Token-%EC%86%8C%EA%B0%9C-%EB%B0%8F-%EA%B5%AC%EC%A1%B0
https://mangkyu.tistory.com/56
https://velopert.com/2389

좋은 웹페이지 즐겨찾기