6월8일 수요일

HSKwon·2022년 6월 8일
0
post-thumbnail

안녕하세요 여러분! 더운 날씨에 건강 유의하시면서 오늘도 힘차게 시작합시다!✨
오늘은 정말 중요한 내용 중 하나인 로그인 파트에 대해서 배웠어요!

간략히 요약하면, Backend는 어떤 사람이 api를 요청하는지 알 수 없기 때문에 유저의 모든 api 요청에 accessToken을 함께 보내줬습니다! http request header의 authorization에 Bearer 방식으로 accessToken을 첨부해서 보냈죠?

이 토큰을 받은 Backend는 accessToken을 열어서 그 안에있는 객체(JSON)의 내용물을 보고 누가 요청을 한건지 구분 할 수 있던 것이였습니다!
이러한 작업이 가능한 이유는 accessToken이 JWT(Json-Web-Token)이기 때문이었습니다.

이를 이해하기 위해 암호화(Encoded)와 복호화(Decoded)에 대해 알아봤죠? JWT는 유저의 이름, id, 만료시간 등 을 객체로 만들고 이를 암호화/토큰화 시켜 브라우저에 전달하는 방식이였습니다!

이 방식으로 Browser에서 요청이 들어오면 더 이상 DB에서 토큰을 찾지 않고, Backend에서 바로 복호화를 통해 로그인 처리를 할 수 있게 된 것이였습니다!

JWT에 단점이 있었어요! 누구든 이 파일을 읽을 수 있다는 점 이였습니다. 그렇다면 JWT를 탈취해 내용을 읽고 변경하게 된다면, 보안상 문제가 커지겠죠! 이를 방지하기위해 서명처리(비밀번호 처리)한다고 했습니다. JWT발급 시 함께 나오는 password가 있는데, JWT 내부의 내용을 누구나 읽을 수 있지만 이 비밀번호가 없다면 조작이 불가능했습니다!

따라서, JWT 내부에는 중요한 개인정보 등을 담으면 안된다는 중요한 포인트가 있었습니다!
암호화 2가지 방법도 알아봤습니다. 오늘 앞선 과정에서 암호화와 복호화에 대해 알아봤죠!

암호화와 복호화 둘 다 가능한 것을 양방향 암호화, 암호화는 가능한데 복호화가 되지않는 단방향 암호화가 있다고 했습니다!
비밀번호 같은 정보는 단방향 암호화를 사용해 복호화 시킬 수 없게 한다고 했죠!

복호화가 되지 않는다는 말은 암호화된 정보가 탈취되어도 그 정보가 어떤 정보인지 알 수 없다는 말이겠죠! 이런걸 Hashing이라 합니다!
이 모든 절차를 통해 API요청 시 토큰을 함께 보내 인증(Authentication) 과 인가(Authorization)를 받아야 했습니다.

그러기 위해 로그인을 하여 받게되는 accessToken을 HTTP header에 Authorization(인가)에 Bearer 방식으로 담아 넘겨주었습니다! 여기서 Bearer는 토큰 관련 정보가 담겨있다는 걸 알려주기 위한 이름일 뿐이라 했고 관례상 붙여주는 것 이였습니다!

이 부분을 우리의 프로젝트에도 적용해봤죠!
그렇게 하면서 ApolloSetting 컴포넌트를 만들어서 Apollo 관련 소스코드는 따로 관리해주었습니다! 그럼 app.tsx를 더 깔끔하게 관리할 수 있겠죠? 이렇게 컴포넌트 형식으로 관리해주시는 것이 리액트의 핵심입니다!

다시 돌아가서 app.tsx에서 recoil을 사용해 accessToken과 setAccessToken을 넘겨 주면 되겠습니다. 이 과정에서 넘겨줄 내용들을 atom을 사용해서 담아 묶어 전달하였습니다!

로그인 화면에서 로그인을 하여 받게되는 accessToken을 recoil을 통해 _app.tsx에 state로 저장하였고,

uploadLink내 headers에 accessToken을 추가해 주었습니다. 이로써 모든 컴포넌트에서 gql-api요청 시, 로그인 관련 정보를 함께 보내줄 수 있도록 설정해주었습니다!

오늘 한 내용을 모두 외우려 하지 마세요, 흐름을 이해하시고 기능을 구현하실 수만 있으면 됩니다!

1️⃣ 첫번째시간

로그인과정(옛날방식)_백엔드의 메모리 세션에 저장하는 방식(사용량이 적은 서비스에서는 요즘도 사용되고 있음//단, 사용량이 늘어날 경우 문제발생가능)

브라우저 입력 => 백엔드의 메모리에 저장됨 => DB의 엑셀에 저장
(cf. 디스크:영구 저장되는 장소)
디스크:영구저장, 저장하거나 꺼내올때 속도가 느림
메모리:영구저장x, 저장하거나 꺼내올때 속도 빠름

브라우저 로그인정보 입력=>로그인api요청=>로그인 정보가 맞다면 백엔드정보에 메모리세션으로 저장 => 세션id를 브라우저로 돌려줌 => 브라우저 저장소에 저장해놓음(ex.쿠키)


예를 들면 백엔드의 createProduct를 사용한다면 상품등록정보(가격, 이름, 설명 등등), uuid(qwrr_아무이름이나썼음)를 보내줘야함

메모리세션의 uuid(qwrr) 만료시간이 남아있다면 로그인 확인 절차 성공
혹은 메모리세션에 로그인 정보가 없거나 만료시간이 남아있지 않다면 에러메세지를 던지게됨

로그인 확인 절차 : 인가 : Authorization
(인증:Authentication과는 다름)


🤔 만약 1명, 10명이 접속하다가 1,000명, 10,000명이 접속한다면....?
컴퓨터 메모리를 초과하는 요청이 들어온다면...? 서버가 터지게 되는 현상 발생!

해결방법?

1.메모리를 증가시키는 scale up(컴퓨터 내에서)
2.다른 컴퓨터 더 구해서 동일한 백엔드 실행시켜놓기 (scale out 방식)
❌ scale out 방식의 문제점 : 서로 다른 백엔드 컴퓨터에서 저장해놓은 로그인 정보가 서로 다를 수 있게됨 //// 서로 다른 백엔드 컴퓨터들이 동일한 로그인 정보를 갖도록 동기화 시키는 과정이 어려움!!!!!!


메모리에서 저장하던 세션 정보가 DB로 넘어오게 되었음

🤔 백엔드의 부하는 어느정도 해소되었지만 DB로 트래픽이 몰리면 어떻게 할것인가...?

❌ 다른 DB를 구해서 모든 내용을 복사시키는 방법으로 해결은 쉽지않음


=====> '나눠서 담기'가 해결책이 될 수 있음

디스크:영구저장, 저장하거나 꺼내올때 속도가 느림
메모리:영구저장x, 저장하거나 꺼내올때 속도 빠름


⭐️ 객체 형태 자체를 암호화하고 복호화되면 객체 형태로 되는 형태를 발견함
결국 db에 저장할 필요 자체가 없게 된것임 (자바스크립트 객체 : JSON JasonWebToken⭐️ JWT 토큰을 복호화 하면 되기 때문에 DB, Redis에 접근하지 않아도 되게 됨 ⭐️)

2️⃣ 두번째시간




1.객체들(JSON)을 암호화 해서 asdfasdf의 키값을 브라우저에 던져주었음!

2.asdfasdf를 백엔드로 보내주면 백엔드에서 이것을 복호화함 (복호화해서 객체값 확인가능)
-만료기간 내일이니까 (YES OR NO) 에서 YES(로그인허락) => 상품 등록

초점을 집중할 곳은 ⭐️인가⭐️ (DB를 거치지 않고 백엔드 자체에서 asdfasdf를 복호화)

복호화 했을때 JSON객체가 나오기 때문에 JWT 토큰이라고함

ㅁ accessToken : 인증 용도의 토큰

오른쪽의 accessToken을 state에 저장해놓아야함
(암호화하고 복호화하는 key는 백엔드에 저장되어 있음)
⭐️key는 백엔드에 저장되어 있지만 누구나 이 jwtToken을 열어볼 수 있음

문제는 accessToken을 입력하면 key가 없는데도 데이터를 볼 수 있다는점
조작된 data인지 아닌지를 백엔드에서 검증할 수 있음
❌카드 계좌번호나 카드번호 등 중요한 data를 데이터에 넣으면 안됨!!!! 딱 인증 용도로만 쓰이는 간단한 정보만 입력해야함


양방향 암호화 : 암호화 하고 복호화 할 수 있음 단방향 암호화(hash) : 암호화를 했는데 복호화를 하지 못한다

pw를 암호 그대로 저장하는게 아니라 암호화 해서 저장한다
(해커들은 암호화 알고리즘을 풀어 복호화를 시도하게 됨)
(그래서 복호화를 하지 못하게 단방향 암호화를 시도하게됨)

🤔도대체 어떤 알고리즘이길래 복호화가 안되는 암호화 방식이 있나...?

182637도 867이고 282637도 867이고 382637도 867 이므로.... 다대일 관계가 되어서 복호화 할 수 없는것임


해커들은 아예 모든 경우의 수를 적은 레인보우테이블을 갖고 여기에서 for문을 돌리려고 시도함 (창과 방패의 싸움)


최근에는 hash에 salt를 쓰는 방향까지 오게되었음

3️⃣세번째시간

header에 bearer accessToken이 추가되지 않아서 정상적으로 출력되지 않는 모습


⭐️accessToken(result.data.loginUser.accessToken)을 recoil화 해서 필요한 곳마다 뽑아쓰자

profile
공부한 내용이나 관심 있는 정보를 글로 정리하며 익숙하게 만들고자 합니다.

0개의 댓글