완성된 프로젝트를 돌아보면 든 생각이 있어요.
구현은 했는데.. 내가 다 이해하고 사용한게 맞나?
그래서 주요 개념들에 대해 학습하고
그 내용들을 포스팅하며 정리하는 시간을 가지려 해요.
정리 후에는 리팩토링하는 시간도 가지고요!
첫 번째 공부 주제는 로그인입니다!
로그인은 사용자의 주요 정보를 다루는 기능이기 때문에
보안이 굉장히 중요해요.
spring에서는 보안이 튼튼한 로그인 구현을 위해
여러 가지 기능들을 제공합니다.
한번 살펴볼까요?
1. 인증과 인가
먼저 인증(Authentication)가 인가(Authorization)에 대해서 알고 넘어가야 한다.
1) 인증
사용자의 신원을 확인하는 과정이 인증이다.
비행기 티켓을 구매하려면 여권을 보여줘야 하는 것처럼
어떠한 사이트에 접속하기 위해서는 아이디와 패스워트를 입력하는 것이다.
2) 인가
사용자가 권한을 얻는 과정이 인가이다.
비행기에 탑승할 때는 여권을 보여줘 증명하지 않아도 된다. 비행기 티켓이 있기 때문이다.
인터넷에서는 티켓의 역할을 하는 것이 토큰이다.
2. Spring Security
애플리케이션의 보안을 담당하는 Spring 하위 프레임워크이다.
저 자세한 설명을 아래 블로그를 참고 바란다.
아키텍처 흐름대로 설명해주시고 실제 코드까지 있어서 설명이 기가막히다👍
한번에 이해가 되진 않아서 두고두고 보며 익혀야 할 거 같다.
3. Oauth2
인증을 위한 개방형 표준 프로토콜이다.
리소스 소유자를 대신하여 리소스 서버에서 제공하는 자원에 대한 접근 권한을 위임하는 방식을 제공한다.
구글, 페이스북, 카카오, 네이버 등에서 제공하는 간편 로그인 기능도 Oauth2 프로토콜 기반의 사용자 인증 기능을 제공하고 있다.
4. JWT
JWT에 대해 본격적으로 알아보기 전에
이해에 도움이 되도록 Session, TCP, CIA, RSA, RFC문서에 대해 짚고 넘어가겠습니다.
출처)
1) Session
요청을 받을 때 세션 목록을 확인하여 최초 요청이면 새로 세션을 만든다.
서버 중지 or 사용자가 브라우저 종료 or 일정 시간(보통 30분)이 충족되면 세션이 사라진다.
이 방식의 단점
동시 접속자수가 많으면 여러 서버를 두어 부하를 분산 처리 즉, 로드밸런싱을 한다.
만약 서버1에 최초 요청을 하면 서버1에 세션 목록이 있는데 다음 요청을 서버2에 한다면 최초 요청으로 인식되는 문제가 발생한다.
여러 해결 방법이 있지만 제일 편리한 것은 공용 DB를 두는 것이다.
하지만 하드디스크까지 접근하여 확인하는 것은 속도면에서 매우 비효율적이다.
그렇기에 Redis와 같은 메모리 공유 서버에 세션값을 저장한다.
Spring Security만 사용할 경우 세션을 사용하는 것이다.
2) TCP
응답 신호(ACK)가 와야 다음 요청을 하는 통신 방법이다.
신뢰성은 높지만 속도가 비교적 느리다.
반면에 UDP 통신의 경우 응답 신호가 오지 않아도 요청을 계속 진행한다.
신뢰성은 비교적 낮지만 속도가 빠르다.
전화의 경우 UDP 통신이라 좀 전화가 끊겨도 요청을 받는 곳이 사람이기에 대략적 이해가 가능하지만
웹의 경우는 그렇지 않기 때문에 TCP 통신을 사용한다.
통신할 때의 문제점은 2가지이다.
1. 정보 전달자를 신뢰할 수 있는가
2. 보안을 유지하며 어떻게 전달할 것인가
3) CIA
기밀성(Confidentiality) + 무결성(Integrity) + 가용성(Availability)
보안의 3요소이다.
4) RSA
암호화 방법 중 하나이다.
공개키(Public Key)와 개인키(Private Key)로 구성되어있다.
공개키로 잠긴 것은 개인키로 풀 수 있고, 개인키로 잠긴 것은 공개키로 풀 수 있다.
공개키로 잠그는 것을 암호화, 개인키로 잠그는 것을 전자서명이에 사용된다.
첫 번째 문제인 "정보 전달자를 신뢰할 수 있는가"의 경우
- A의 개인키로 잠궈서 B에게 전달
- 해커는 A의 공개키을 사용하여 접근이 가능하지만 중요 내용이 아니기에 괜찮음
- B는 A의 공개키로 접근. A의 공개키로 접근이 된다는 것은 A의 개인키로 잠궜다는 것이고 , A의 개인키는 A만 가지고 있기 떄문에 신뢰 가능
두 번째 문제인 "보안을 유지하며 어떻게 전달할 것인가"의 경우
- A가 B의 공개키로 잠궈 전달
- 해커는 B의 개인키가 없기에 접근 불가
- B의 개인키를 갖고 있는 B만이 접근 가능
위 방법으로 해결이 가능하다.
그래서 통신할 때 B의 공개키로 1차 잠그고 A의 개인키로 2차 잠궈서 B에게 전달하면 CIA를 충족하면서 전달이 가능하다.
5) RFC 문서
통신을 위해 약속된 프로토콜을 작성한 문서이다.
RFC 문서를 충족한 것이 WWW(월드 와이드 웹)이다.
6) JWT
JSON Web Token
정보를 JSON 객체로 안전하기 전송하기 위한 개방형 표준으로 RFC 문서에 작성되어 있다.
Security는 복호화가 되지 않아 비밀번호 수정이 아닌 초기화를 해야 하는 반면,
JWT는 Base64로 인코딩되어 있어 암호화와 복호화가 가능하다는 장점이 있다.
구조
1. Header
어떤 암호화 알고리즘을 사용했는 지가 담긴다.
HS256가 RSA가 있다.
HS256 = HMAC(시크릿키를 포함한) + SHA256(해쉬)
2. Playload
claim이 가지고 있는 정보이다.
claim은 등록된 claim과 개인 claim으로 나뉜다.
- 등록된 클레임 : 필수는 아니지만 권장하는 집합 ex) 발행자, 만료시간, 주체, 청중 등
- 개인 클레임 : 유저 아이디 등
3. Signiture
Header + Payload + private key
흐름
1. 클라이언트가 서버에게 정보를 주면서 로그인을 시도
2. 서버는 정보를 담은 JWT 토큰을 만들어 반환
3. 클라이언트가 서버에게 정보를 달라고 요청
4. 서버가 알고 있는 Header + Payload + private key 조합으로 나온 Signiture값과 클라이언트가 요청하면서 준 JWT 토큰 속 Signiture값이 같으면 신뢰할 수 있는 요청으로 인식하여 Payload에 담긴 정보를 반환
더 깊이 알아보려하면 끝이 안 날 거 같아 전반적인 흐름을 이해하고
왜 이 기술을 쓰는 지 알 수 있을 정도로만 정리해보았습니다.
세션보다 JWT가 좋다고 기술했으나 JWT가 단점이 아예 없는 것은 아닙니다.
상황별로 더 잘 맞는 것을 사용하면 될 거 같습니다.
'JAVA > [개인프로젝트] GooGoo' 카테고리의 다른 글
JDBC, JPA, Spring Data JPA 차이 그리고 Hibernate와 ORM (0) | 2023.10.13 |
---|---|
CSR VS SSR (0) | 2023.09.10 |
[외부 API 호출] RestTemplate, WebFlux (WebClient) 그리고 WebSocket (0) | 2023.09.02 |
[Spring Boot] 최고의 프로젝트 구조는 무엇일까? (0) | 2023.08.30 |
[JAVA] Selenium으로 구글 로그인 자동화 만들기 (0) | 2023.07.29 |