1.
로그인할 때, 사용자가 입력하는 id, password를 db에 기억하고 있다가 같으면 로그인 X
-> db가 해킹 당하면 전부 유출되는 문제가 존재.
2.
페이지를 들어갈 때마다 로그인 상태를 '유지' 시켜주는 문제
So, 인증, 인가가 중요
- 인증 : Authentication (로그인)
- 인가 : Authorization (로그인이 유지되는 상태에서 일어나는 것)
1. 사용자가 로그인에 성공하면 '서버'는 '세션 딱지'같은 걸 출력한다.
이 딱지를 찢어서 반쪽은 '사용자의 브라우저'로, 반쪽은 '메모리, db ... ' 등 에 저장함.
(메모리에 저장하는게 다른 저장 공간보다는 빠르게 처리해준다.)
2. 브라우저가 이 딱지를 session ID란 이름의 쿠키로 저장 (쿠키 : 브라우저에 저장되는 정보)
이 브라우저는 다음 사이트에 요청을 보낼때마다 이 딱지를 실어 보냄.
3. 요청에 session ID라는게 들어오면 -> 서버는 메모리에서 맞는 짝이 있는지를 찾는 것
어떤 사용자가 서버에 로그인 되어있음이 지속되는 상태를 '세션'이라고 함
- 서버가 표 반쪽을 기억해두고 있는 자체
- 사용자가 동시에 많이 접속하면 메모리가 부족해질 것
-> 메모리 특성상 서버에 문제가 있어서 꺼져버리기라도 하면 정보가 날라감 (휘발성)
사용자는 다시 로그인해야하는 상황이 발생
- 메모리 대신 하드에 저장을 하면? 메모리보다 느리다.
- 서버를 여러대 둔다면? (서버를 분산해서 load balancing)
만약에 로그인은 1번 서버, 검색 요청하는 서버는 2번 서버에 연결을 하면 2번 서버에는 그 사용자에 대한 정보(딱지)가 없으니 세션 유지가 되지 않음.
- 복잡한 구성과 환경에서 (사용자가 많아져서 메모리가 부족해진다던지, db에 연결을 하면 무거워진다던지) 어떤 상태를 기억해야한다는 설계가 힘듦
- json web token
- jwt를 사용하는 서비스에서는 사용자가 로그인을 하면 'token'이라는 표를 (세션때와 마찬가지로) 출력해서 줌
대신 세션 때와 다른 점은 '찍어서 주지 않고' 그냥 준다. 즉, 서버가 뭔가를 기억하고 있지 않다는 점
- 토큰의 생김새 : feihfisfnjskldoujkalHUgirgeg....
인코딩/암호화된 3가지 데이터리를 이어붙임 (잘 살펴보면 중간에 마침표가 2개 들어가있다.)
각각 header, payload, verify signature로 구분됨
(1) payload 부분
- (base64로) 디코딩을 해보면 json 형식으로 여러 정보들이 들어있음
이 토큰을 누가 누구에게 발급했는지, 언제까지 유효한지, 서비스가 사용자에게 이 토큰을 공개하기 원하는 내용 (사용자 닉네임, 관리자 여부 등) 등의 정보가 있는데 서비스 측에서 원하는대로 담을 수 있음
- 이렇게 토큰에 담긴 사용자 정보 등의 데이터를 claim이라고 함
- 사용자가 이런 정보(claim)을 갖고 있으니, 서버는 요청이 들어올 때마다 일일히 db에서 찾아봐야 할 수고가 줄어들게 됨
- 허점 : 디코딩해서 볼 수 있기에, 보안에 허점이 존재 (그래서 header, verify signature가 필요)
(2) header 부분
- 디코딩해서 보면
1) type : 토큰 타입 (여기에는 언제나 jwt가 들어간다. 타입이 jwt여야 jwt인 것이기에 고정값이다.)
2) alg : 알고리즘의 약자. verify signature을 만드는데 사용될 알고리즘이 지정됨.
예를 들어 HS256 등 여러 암호화 방식 중 하나를 지정한다.
header, payload, '서버에 감춰놓은 비밀 값' 이렇게 3개를 이 알고리즘에 넣으면 -> verify signature가 나온다.
- 서버는 요청에 토큰이 들어오면, header, payload, '서버에 감춰놓은 비밀 값'을 계산해봐서 계산된 결과값이 verify signature 와 같은지를 확인한다.
- 만약 header, payload 중에 조금이라도 어떤 정보가 수정되었다면 패스가 되지 않음.
✅ 이처럼 시간에 따라 바뀌는 어떤 상태값을 '안' 갖는 걸 'stateless하다'고 함 (반대는 stateful)
- 세션을 대체하기에는 jwt 방식에는 큰 결점이 존재
세션처럼 stateful해서 모든 사용자들의 상태를 기억하고 있으면, (구현이 부담스럽지만) 기억하는 대상의 상태를 언제든 제어할 수 있음
ex) 기기 한 대에서만 로그인 가능한 서비스를 만들었는데, 세션 방식으로 하면 다른 기기에서 로그인을 해왔을 때 pc에서는 로그아웃되도록 컨트롤 가능
<-> 반대로 토큰은 한 번 줘버리 토큰은 회수도 추적도 불가능. 즉, 내가 정보를 가지고 있지 않아서 편하기는하나 통제가 불가능
더 최악의 상황은 어떤 해커가 토큰을 가져가버리게 되면 그 토큰을 무효화시킬 방법이 없음
- 서버가 아는 것은 오직 토큰이 유효한지 여부. 유저 계정을 잘 관리해야 하는 경우 session을 활용한다.
(session처럼 db에 저장하지 않기 때문에 현재 인스타그램에 로그인한 계정이 몇 개인지, 넷플릭스 한 아이디에 몇 명의 유저가 쓰고 있는건지 등을 확인 불가)
- 그래서 생각보다 jwt를 많이 쓰지 않는다.
jwt를 사용하는 경우는 만료 시간을 가깝게 잡아서 토큰의 수명을 아주 짧게 주는 경우.
1) access 토큰 : 수명이 몇 시간이나 몇 분이하로 짧음
2) refresh 토큰 : 꽤 길게 (2주 정도) 수명이 있음
- access 토큰과 refresh 토큰을 발급하고 클라이언트에게 보냄
- refresh 토큰은 상용값을 db에도 저장함
- 클라이언트는 access 토큰 수명이 다하면 refresh 토큰을 보냄
- 서버는 그 토큰을 db에 저장된 값과 대조해보고 맞다면 새로운 access 토큰을 발급해줌
- refresh 토큰만 안전하게 관리된다면 이게 유효할동안은 access 토큰이 만료될 때마다 다시 로그인할 필요가 x
(아래는 기존에 작성했던 내용인데 삭제하려다가, 위에 내용으로 확실히 개념 잡고 다시 읽어봐도 될 것 같아서 남긴다. (흐름이 산재되어 있기에 개념 잡고 읽으면 흐름을 스스로 잡는데 도움이 될 듯ㅎㅎ))
쿠키
stateless 개념
session
jwt
캐시
캐시 vs 쿠키
-> 캐시 는 로딩 시간을 줄이기 위해 브라우저 (클라이언트 측)에 웹 페이지 자원을 저장하는 데 사용되는 반면, 쿠키 는 사용자 기본 설정을 추적하기 위해 브라우징 세션을 저장하는 데 사용
출처 : https://youtu.be/tosLBcAX1vk, https://youtu.be/1QiOXWEbqYQ
캐시 vs 쿠키 : https://ko.gadget-info.com/difference-between-cache
캐시 출처 : 책 [it인프라구조]
호스팅형 vs 설치형 (feat. Cloud hosting vs Self hosting) (0) | 2022.02.07 |
---|---|
[node] Error.captureStackTrace() (feat. 문제 해결력을 증진시키는 flow) (0) | 2022.02.07 |
node - middleware) express-validator (0) | 2022.01.26 |
[js] 생성자 (0) | 2022.01.24 |
ESLlint (1) | 2022.01.24 |