로그인 기능 구현은 크게 두 가지 부분으로 나뉠 수 있다. 바로 인증과 인가이다.
인스타그램을 예시로 들자면,
인스타그램에 로그인하는 것이 '인증'하는 것이고
로그인된 계정으로 친구들의 스토리를 보고 피드를 보거나 댓글을 다는 등 해당 사용자 계정으로'만' 할 수 있는 활동을 시도할 때 서버에서 로그인되어있음을 알아보고 허가해주는 것이 '인가'이다.
쿠키 인증 방식은 쿠키에 사용자의 인증 정보를 담아서 인증하는 방식이다.
❓ stateless와 stateful
stateless는 무상태로, 클라이언트-서버 관계에서 서버가 클라이언트의 상태를 보존하지 않음을 의미한다.
- Stateless 구조에서 server는 단순히 요청이 오면 응답을 보내는 역할만 수행하며, 세션 관리는 클라이언트에게 책임이 있다.
- 따라서 Stateless 구조는 클라이언트와의 세션 정보를 기억할 필요가 없으므로, 이러한 정보를 서버에 저장하지 않는다. 대신 필요에 따라 외부 DB에 저장하여 관리할 수 있다.
stateful 은 상태유지로, 클라이언트-서버 관계에서 서버가 클라이언트의 상태를 보존함을 의미한다.
- 클라이언트의 이전 요청이 서버에 잘 전달되었을 때, 클라이언트의 다음 요청이 이전 요청과 관계가 이어지는 것을 의미한다.
👍장점:
👎단점:
세션 인증 방식은 세션으로 사용자의 인증 정보를 관리하는 방식이다.
👍장점:
1) 한 사용자의 디바이스별 인증을 관리할 수 있다.
2) 하나의 계정 공유를 관리할 수 있다.
3) 비정상적인 접근 신고가 들어오면, 서버에서 판단하여 해당 세션을 삭제해서 바로 로그아웃시킬 수 있다.
사용자 인증 정보를 관리하는 곳은 크게 메모리, 하드 디스크, DB 이렇게 3가지이다.
1. 메모리 영역/하드디스크
토큰의 방식 중 JWT 토큰이 가장 간단하고 대표적이다.
클라이언트가 인증 정보를 관리하기 때문에 stateless하다.
인증/인가 flow는 다음과 같다.
1) 클라이언트가 서버에 첫 로그인 인증 요청을 보내면, 서버에서 응답으로 Token을 담아서 보낸다.
2) 서버에서 응답한 Token을 클라이언트에서 저장하고, 인증/인가 요청 시마다 서버로 요청한다.
👉 JWT를 간단하게 설명하면, 사용자의 인증 정보와 서버의 SecretKey로 서버가 생성한 Token이다.
- 여기서 중요한 점은 '서버의 SecretKey로 서버가 생성한 Token'이라는 점이다!
- 클라이언트가 Token을 저장하고 인가 요청 시에 발급받은 Token을 사용하여 요청을 보내기 때문에 Token을 클라이언트가 관리한다는 점은 쿠키 인증 방식과 비슷하지만, 서버에서도 해당 Token에 대한 SecretKey를 가지고 있다는 점에서 쿠키 인증 방식과 다르다.
- 앞에서 말한 '토큰 검증'이라는 것이 바로 요청으로 온 Token이 서버에서 발급한 Token인지 검증하는 단계이다. 이때, 요청으로 온 Token의 SecretKey가 다르다면 위조, 변조된 Token이라고 판단하여 인증 에러를 발생시키게 된다.
이러한 검증 단계를 거치기 때문에 쿠키 인증 방식보다는 보안상 훨씬 안전하다.
추가로, 세션 방식과 비교해서는 기본적으로 클라이언트가 Token을 관리하기 때문에 서버 부하가 비교적 덜하다는 장점이 있다.
하지만, Token을 검증하는 것뿐이지 해당 Token을 관리하는 것이 아니기 때문에 세션보다 보안상 취약하고 비정상적인 유저라고 판단 시 Token을 만료하거나, 디바이스별 제어 등 세션에서 가능했던 부분들이 불가능하다.
위에서 설명한 Token은 모두 AccessToken을 의미하고 물론 RefreshToken을 사용하면 가능해지긴 하지만 세션 방식에 비해서는 완벽하지 못하다.
🔖 출처: