Wecode 부트캠프 -Foundation 2/인증, 인가- 개념

Foundation 2 - 인증 : token, session,

JBS 12 2023. 9. 6. 14:27

그래서 인가 어떻게 하는건데? 

  • 백은 프론트에게 무엇을 전달 받아야하고, 
  • 백은 프론트에게 무엇을 받아서 무엇을 줘야 하는지 → 기술 스택 명확하게 알아야 함. (기술적 펼처짐 이해) unless, 변수, 에러 → 전체 flow 이해 (내가 작성한 소스 코드가 어떠한 결과를 내기 위해 존재하는지 알아야 함) 

 

HTTP 사용 :  웹 환경에서 사용자 - 시스템 사이 데이터 교환 

 

HTTP의 대표적 특징

: stateless (“상태없음”: 독립적, 과거 통신에 대한 이력이 저장되지 않는다: 언제? 한번의 request, response 생애 주기가 끝나면, 소멸됨 → 그래서 header에 다양한 메타 정보_과거 이력 동봉해서 보냄 )

 

그럼, 인증 인가 어떻게 해? Stateless인데? → 매번 요청할때마다 인증 절차를 해야하는 불편함 해소를 위해, 사용자 정보에 한해서 특수 정보는 ‘임시적인 statelss 상태를  stateful 상태로 만든다!  (session, token, cookie를 사용!) 

 

 

cookie,token, session 

Cookie

  • 클라이언트의 컴퓨터에 저장되는 데이터 파일
  • 이름, 값, 만료 날짜/시간(저장기간), 경로 정보 등으로 구성
  • 하나의 도메인 당 20개를 가질 수 있으며, 1개 당 4Kbyte를 넘길 수 없음

 

  • 서버에서는 HTTP Response Header에 Set-Cookie 속성을 이용하여 클라이언트에 Cookie를 제공하여 저장하게 함 (임시저장해야하는 것들이야!) 
  • 클라언트는 HTTP Request에 저장된 Cookie를 함께 전달하여 이전의 통신에서 사용된 정보들을 파악
  •  Cookie를 이용하여 로그인을 하지 않은 상태로 장바구니에 상품을 담을 수 있게 구현 가능 (로그인 안했는데 장바구니 담기고 결제페이지 그때가서 로그인하라고 하는, 사용자 입장: 비회원 주문 가능하네? 귀찮지 않네> 사버리자 - 결제로 이어지는 진입장벽 낮아짐>> - 입사한 회사의 서비스 분석해서, 기획회의에서 우리 제품 이런 특징 지니니, 이런 기술 스택을 가지고 우리 고객에겐 훨씬 낮은 허들의 진입장벽을 제공해야겟구나 그려져야: 내가 쓴 코드가 고객에게 왜 필요한지 생각 ) 
  • 사용자별로 다른 정보를 표시하는 것이 가능, 사용자의 행동과 패턴을 분석할 수 있기 때문에 최근들어 더욱 중요한 개념이 되었습니다. Ex. 구글 애널릭스: 퍼포먼스 마케킹에서 고객의 이동경로 행적 -전단계,전전단계 이동단계 유츄할 수 있게 해줌

너가 짠 코드로 고객이 결제 단계로의 왔으니, →쿠키에 저장된 임시정보로 가능

 

Session :

서버가 관리하는 

  • 클라리언트(사용자)가 브라우저를 통해 웹 서버에 접속한 시점으로부터 브라우저를 종료하여 연결을 끝내는 시점으로부터 브라우저를 종료하여 연결을 끝내는 시점 동안 클라이언트와 웹 서버가 논리적으로 연결된 상태
  • 서버는 session정보를 저장하고 클라이언트에게는 session을 구분할 수 있는 session id 를 부여  (쿠키 형태로 저장하고 잇다가 session id 준다. 아까 그 사람이네 하고 싶은 거 다해 - 백엔드가 발급, 종료 전까지 머물고 잇다가, 매번 특정 회원의 요청으로 서버 보낼때, session id를 쿠키로 가져와서 다시 확인하는)
  • 클라이언트 request를 보낼 때 해당 session id를 함꼐 보냄으로써, 클라이언트의 상태를 확인

 

Session과 Cookie를 이용한 인증 Flow

신입개발자는 도식화, 모식화 (펜과 종이 항상)

위코드에서는 token 기반의 인증인가할 것.  (늘, 3개 중 하나를 선택에 대한 근거 명분 제시할 줄 알아야!)

이 기술 외의 cookie, session 이론에서 배움. 

 

 

 

  1. 사용자가 로그인을 하기 위해 인증 정보를 가지고 인증 과정을 요청 
  2. 인증이 완료 되면 사용자의 Session 정보를 서버의 메모리에 저장 
  3.  해당 Session을 식별할 수 있는 Session ID 발급
  4. 발급한 Session ID를 사용자에게 전달 
  5. 전달받은 Session ID는 브라우저의 Cookie에 저장 
  6. 사용자가 Request를 서버에 보낼 때 함께 전달 
  7. 서버는 사용자가 보낸 Session ID 와 서버 메모리/데이터베이스에서 관리하고 있는 Session ID를 비교

 Session 기반 인증의 특징

Sessionid 는 cookie에 들어가 있음 

 장점

  • Session ID 자체에는 유의미한 개인정보가 없음
  • 서버에서 정보를 관리하기 때문에 데이터의 손상 우려에 대해 상대적으로 안전 (백엔드가 권한많음)
  • 서버에서 상태를 유지하고 있으므로, 사용자의 로그인 여부 확인이 쉬움
  • 경우에 따라서 강제 로그아웃 등의 제재를 가할 수 있음 (넌 인증 인가 안한 회원이야, 빠꾸 먹을 수)

단점

  • 서버에서 모든 사용자의 상태를 관리해야 되므로 사용자의 수가 증가 할 수록 서버에 가해지는 부하가 증가 
  • 사용자가 증가하여 서버의 Scale Out(증가하는 트래픽 관리)을 해야 할 때 Session의 관리가 어려워짐
  • 멀티 디바이스 환경에서 사용 할 때 중복 로그인 처리가 되지 않는 문제 등 신경 써줘야 할 부분 들이 증가 (이미 로그인한 사람이 다른 디바이스로 로그인할때, ‘이미 로그인한사용자가 있습니다')

Token based 인증

Token

Ex. 암행어사 마패 (일반 서민들이 막 난리칠때, 중요한 순간에 문 박차고 나가면 마패로 ‘이거 나야, 너 문열어 뒷 곳간 열어서 확인하게 해줘' 일반 서민들이 미안하다고 막 도망감)

  •  Token의 사전적 의미는 버스 요금이나 자동판매기 등에 사용하기 위하여 상인, 회사 등에서 발행한 동전 모양의 주조물 
  • 웹에서의 토큰도 이와 비슷한 의미를 가지고 있음
  • Token을 가지고 있으면 해당 서비스를 이용할 수 있는 권리가 있다고 간주
  •  제한된 리소스에 대해 일정 기간 동안 접근할 수 있는 권한을 캡슐화 
  • Token은 일반적으로 의미를 알 수 없는 임의의 문자열 형태로 사용자에게 발급 
  • 접근 할 수 있는 리소스의 범위와 접근 가능한 기간 또한 통제 가능

토큰에 다양한 정보 담길 수 있고, 백엔드가 의도해서 넣은건데, 

나중에 사용자가 가져온 거를 백엔드는 정보 분석해서 활용하는것!

Token을 이용한 인증 Flow

  1. 사용자가 로그인으로 을 하기 위해 인증 정보를 가지고 인증 과정을 요청 
  2. 인증이 완료 되면 사용자의 식별 정보를 가지고 있는 Token을 발급 (jwp만들고)
  3. 발급한 Token은 Response의 Body에 담아 사용자에게 전달 (백엔드는 jwp 분석하고, 아까 그애 맞네?)
  4.  발급된 Token을 local storage(웹브라우저)에 저장  (프론트는 Jwp를 로컬 저장소에 저장)
  5. 사용자는 Request를 할 때마다 저장된 Token을 Header 에 포함시켜 서버로 전달
  6. 서버는 사용자로부터 전달받은 Token 정보를 Verification 한 뒤, 해당 유저에 권한을 인가 (= 아까 근 사람, 맞네, 원하는거 다 들어줄게, 암행어사 마패 인증) 

 Token 기반 인증의 특징

장점

  • Token을 사용자 측에서 저장하므로 서버의 메모리나 DB 등의 부담이 없음 (session은 서버 부담이 컸음).
  • 사용자의 상태 정보를 서버에서 관리하지 않기 때문에 서버의 Scale Out에 용이
  • 모바일과 브라우저의 멀티 환경에서 사용이 용이
  • Token의 만료 시간 설정 가능 →  만료 시간 짧게 해서 안정성 증가 

단점

  • 사용자의 로그인 여부 확인 및 강제 로그아웃 등의 제재를 가하기 어려움 (로그인 여부 확인 못함, 올바른 회원이다라는 인가과정을 계속 거쳐야함)
  • 사용자가 임의로 토큰을 수정하거나 구조가 변경되게 되면 서버에서 확인할 수가 없음.
  • Payload 부분에 사용자 식별을 위한 여러 정보들이 포함 되어 있어 Session Id의 길이보다 길어져 HTTP request 전송 데이터의 크기가 증가
  • XSS 공격에 취약하여 Payload에 민감한 정보를 포함하는 경우 위험함 (민감 정보 포함하면 원래 안된ㄴ데, 최소한의 민감 정보 줘야하긴 함- 그럼 악성 공격 대응 어려움) 
너는너 나는나 노노
프론트는 항상 백엔드가 뭐하는지 궁금해햐야 
백엔드는 항상 프론트를 궁금해해야 

 

Token based 인증의 이점

  • 상태 없음/ stateless :서버측에서 상태 정보를 관리하지 않고, 사용자 측에서 관리하기 때문에 서버의 상태를 stateless하게 유지 
  • 규모의 증가/scalability: 서버의 상태를 stateless하게 유지 되기 때문에 사용자와 서버 사이에 관계가 없음/ 관계가 존재하지 않기 때문에 서비스를 운영 중인 어떤 서버로든지 request를 보낼 수 있고, 서버의 확장에 유리 
  • 보안/security: 서버로 요청을 보낼 때 cookie를 전달하지 않으므로 CSRF 공격을 방지하는 데 도움
  • 확장성/ Extensibility: 토큰 기반의 인증 시스템에서는 토큰을 통해 권한의 범위를 지정할 수 있음/ kakao, facebook, google 등과 같은 소셜 계정을 이용하여 다른 웹서비스에서도 로그인
  • 다중 로그인/ multiple devices and domains : 세션 기반 인증 시스템의 문제점 중 하나인 cors 문제를 해결 / 다양한 기기와 도메인에서도 토큰의 유효성 검사를 진행한 후에 요청을 처리할 수 있음

 

[인증] Bcrypt

  • 단방향 암호화는 해시 알고리즘을 기반으로 만들어졌습니다.
  • 해시 알고리즘의 단점을 보완하기 위해 단방향 암호화에 솔팅(Salting)과 키 스트레칭(Key Stretching) 기술을 적용 시킵니다.
  • Bcrypt는 레인보우 테이블 공격을 방지하기 위해 솔팅과 키 스트레칭을 적용한 대표적인 예 입니다.
  • Bcrypt는 단방향 해시 알고리즘이기 때문에 복호화가 불가능 합니다. 따라서 비교하고 싶은 평문을 암호화된 값이 가지고 있는 알고리즘, Cost Factor, Salt을 이용하여 해시를 진행한 후 암호화된 값과의 비교를 통해 검증을 진행합니다

01. Bcrypt

1-1. Salting & Key Stretching

단방향 암호화에 사용되는 해시 알고리즘은 동일한 평문에 대해서 항상 동일 해시값을 갖습니다. 따라서 특정 해시 알고리즘에 대해서 어떠한 평문이 어떤한 해시값을 갖는지 알 수가 있습니다.

또한 해시 함수의 본래 빠르게 데이터를 검색하기 위해서 탄생 되었습니다. 따라서 공격자는 매우 빠른 속도로 임의의 문자열의 해시값과 해킹할 대상의 해시값을 비교하여 대상자를 공격할 수 있습니다.

이런한 문제를 보안하기 위해 단방향 암호화를 진행할 때 솔팅(Salting)과 키 스트레칭(Key Stretching)을 적용 시킵니다.

1-1-1. 솔팅(Salting)

  • 원본 데이터에 랜덤한 데이터 추가 
  • 데이터가 추가되어 원본과 다른 해시 값 가짐

(솔팅에서 끝나지 않음. 키 스트레칭 통해 솔팅으로 생성된 문자열 다양한 내용들을 비밀번호 거쳐서 해쉬를 거침)

1-1-2. 키 스트레칭(Key Stretching)

  • 해시를 1번만 하는 것이 아닌 여러번 반복 (해시 함수의 난수화 과정을 n번 과정 가능- 키 스트레칭을 통해서- 근데 암호화 많이 하면 안 좋음 다 비용, 속도 저하) 
  • 해쉬값을 다시 해시하는 방식으로 진행 (해시= 단방향으로 난수를 만드는 함수 → 암호화를 햇으면 거기서 끝나는 것, 역방향으로 못 감) 
  • 1초에 50억 개  비교할 수 있지만, 동일한 장비에서 1초에 5번 비교

1-2. Bcrypt 란?

  •  브루스 슈나이어가 설계한 키(key) 방식의 대칭형 블록 암호에 기반을 둔 암호화 해시 함수 Niels 
  • 레인보우 테이블 공격을 방지하기 위해 솔팅과 키 스트레칭을 적용한 대표적인 예 

1-2-1. 구조

  • 2b: 해시 알고리즘 식별자 (해시 알고리즘은 정말 다양함)
  • 12: Cost Factor로 Key Stretching의 수 (2의 12승번)
  • 76taFAFPE9ydE0ZsuWkIZe: 16Byte 크기의 Salt, Base64로 인코딩된 22개의 문자

xWVjLBbTTHWc509/OLI5nM9d5r3fkRG: 24Byte의 해시 값, Base64로 인코딩된 31개의 문자

1-2-2. 검증

  • Bcrypt는 단방향 해시 알고리즘이기 떄문에 복호화가 불가능 (역방향으로 못 감- 새로 들어온 비밀번호를 똑같은 과정으로 암호화된 것을 암호화된 것과 비교)
  • (두 결과의 아웃풋을 비교)

[인증] JWT

토큰 방식 중에,  json web token

 

JavaScript Object Notation (JSON)은 
Javascript 객체 문법으로 구조화된 데이터를 표현하기 위한 문자 기반의 표준 포맷

 JWT의 구조

JWT는 3단 구조 

  • Header, Payload, Signature로 구성(각 구성 요소들은 dot(.)으로 구분)
  • 클라이언트에게 보내야 하는 최소 유저 정보를 payload에 담아서 보내야 함 ( 스파이인지 회원인지 구분)
  • 시그니처: 암호화된 전자 열쇠 (암호키) 내가 작성한 암호키 secret key로 jwt는 만들어졋구나, 열수 잇구나 

 

- payload

유저 정보는 payload에 쓰여잇고 

- signature

특정 유저가 행동 요청 시, 유저 맞구나, 데이터베이스에 잘 기록됏구나 확인 후

활용할 서비스 내용 연결, 가능하게 하는 것 

 

 

 Payload

Payload는 JWT의 두번째 구성 요소로 실질적으로 전달해야 하는 정보들이 있다. Payload에 담긴 정보 하나 하나를 Claim이라고 함

 3가지 종류의 Claim이 존재

 

- Registered Claims: 이미 JWT 표준으로 지정된 Claim 입니다

 

- Public Claims: JWT를 사용하는 사람들이 공개적으로 정의할 수 있습니다. 그러나 기존에 이미 등록되어 있는 Claims와 충돌을 방지하려면 IANA JSON Web Token 레지스트를 참고하거나 UUID, OID, 도메인 이름 등을 사용해야 합니다.

 Public Claims과 달리 오직 사용자와 서버 사이에서만 합의하여 사용하는 Claim 입니다.