ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 세션? 토큰? JWT?
    cs 지식 2021. 7. 24. 18:58

    클래식한 세션관리

    사용자가 로그인에 성공하면 서버에선 세션 티켓인 Sesstion ID를 출력한다. 이 Sesstion ID를 반으로 쪼개서 반쪽은 브라우저에 올리고 반쪽은 서버의 메모리나 하드디스크, 크게는 데이터베이스에 저장한다.

    브라우저는 이 반쪽짜리 Sesstion ID를 쿠키에 저장하고, 서버에 네트워크 요청할 때마다 이 Sesstion ID를 같이 보낸다.

    서버에선 Sesstion ID를 대조해서 사용자의 로그인이 지속되어있는지를 판단하는데, 이걸 세션이라고 한다.

     

    하지만 사용자가 많아질 경우 메모리를 여러개로 관리해야 하거나, 공용창고인 데이터베이스에서 관리하는 등의 방법을 쓰게 되는데, 어떤 에러에 노출되거나, 서버가 재부팅 되면 세션이 초기화되어 사용자들은 다시 로그인해야 하는 리스크가 있다.

     

    JWT(JSON Web Token)

    이 방식을 사용하면 사용자가 로그인했을 때 Session ID를 반쪽을 찢어주는 대신 토큰을 통째로 준다. 그럼 서버는 가지고 있을 반쪽짜리 Session ID가 필요 없이지기 때문에 훨씬 가벼워진다.

    토큰은 인코딩되어있는 문자로 되어있는데, 사용자는 이걸 디코딩해서 누가 누구에게 발급했는지, 언제까지 유효한지, 닉네임 등 사용자 정보 데이터(Claim)을 알 수 있다.

     

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
    
    - 큰 틀은 'xxxx.yyyy.zzzz' 형태
    - xxxx는 헤더, yyyy는 페이로드, zzzz는 서명 값

    JWT 토큰의 형태는 자세히 보면 xxxx.yyyy.zzzz로 되어있다. xxxx는 헤더, yyyy는 페이로드, zzzz는 서명 값인데, zzzz 서명값은 헤더+페이로드+서버에 감춰놓은 비밀값을 암호화 알고리즘으로 돌려서 나온 것이다. 서버에 감춰놓은 비밀값 때문에 다른 사람이 탈취하거나 수정이 불가능하다고 볼 수 있다.

    그래서 서버는 사용자들의 상태를 메모리에 따로 저장해놓지 않아도 이 요청 들어올 때마다 토큰만 스캔해서 사용자가 맞는지 아닌지를 걸러낼 수 있다. 

     

    세션  VS 토큰

    세션은 서버에도 Session ID 메모리를 저장해야 하며 모든 사용자들의 상태를 기억하고 있기 때문에, 특정상황에서 서버가 사용자의 상태를 마음대로 제어할 수가 있다. 예를 들어 한 기기에서만 로그인이 되어야 하는 경우 사용자가 PC에서 로그인했다가 모바일에서 또 로그인 하면 PC에서는 로그아웃되도록 제어할 수가 있다.

     

    JWT로 하면 토큰을 들고 있는 사람은 다 로그인을 할 수 있기 때문에 서버에서 제어를 할 수가 없다. 혹여나 누군가가 토큰을 탈취했을 경우에도 토큰을 무효화할 수 없기 때문에 무방비에 노출될 수 있다.

     

    토큰의 단점을 보완하기 위해 분리된 accessToken과 refreshToken

    유효한 토큰을 가지고 있는 사용자는 유효기간 내에 마음대로 네트워크 요청을 할 수 있기 때문에 탈취될 경우 무방비에 놓일 수 있다는 단점이 있다. 그래서 이것을 보완해주기 위해 짧은 수명의 토큰인 accessToken과 긴 수명의 토큰인 refreshToken으로 나누어서 발급해준다.

    서버에서는 refreshToken의 상응값을 데이터베이스에도 저장해둔다. 사용자는 accessToken의 수명이 다하면 refreshToken을 서버에 보내고, 서버에서는 이걸 상응값과 비교해서 맞다면 새 acessToken을 발급해준다. 사용자는 accessToken이 만료할 때마다 새로 로그인 할 필요가 없는 것이다.

    이렇게 토큰을 두개로 나누면 중간에 accessToken이 탈취당해도 오래 쓰지 못한다. 서버에서는 acessToken을 탈취한 사람을 강제로 로그아웃시키게 하려면 refreshToken만 지워버리면 토큰갱신이 안되어 금방 로그아웃 되어버리게 한다.

     

    하지만 그 사이 몇분 안에도 충분히 난리칠 수 있기 때문에 이 방식의 보안이 철처하다고 볼수는 없다.

     

    'cs 지식' 카테고리의 다른 글

    webpack? babel?  (0) 2021.07.24
    자료구조에 대하여  (0) 2021.07.24
    scope?  (0) 2021.07.24
    동기요청? 비동기요청? promiss? async? await?  (0) 2021.07.24
    브라우저와 통신과정  (0) 2021.07.24
Designed by Tistory.