사용자 인증
인증은 웹 애플리케이션에서 가장 중요한 구성 요소 중 하나입니다. 인증 과정에서 사용자의 신원을 확인하고, 해당 사용자에게 적절한 권한을 부여하는 것이 주 목표입니다. 이번 글에서는 웹에서 널리 사용되는 인증 방법들에 대해 알아보겠습니다!
인증 방법
쿠키
쿠키란 무엇인가?
- 쿠키는 브라우저에 저장되는 작은 단위의 문자열 파일들입니다.
- 이름, 값, 속성값을 저장하고 있습니다.
- 보통 아래와 같은 형식으로 응답 헤더에 담아 서버에서 클라이언트로 전송됩니다.
{
Set-Cookie: user_id=12345; HttpOnly; SameSite=Lax;
}
인증 과정
- 사용자가 로그인 요청을 보냅니다.
- 서버는 사용자의 신원을 확인하고, 유효한 사용자일 경우 `Set-Cookie` 헤더를 사용하여 응답에 쿠키를 포함시킵니다.
- 클라이언트는 이 쿠키를 저장하고, 이후의 모든 요청에 이 쿠키를 첨부하여 보냅니다.
- 이렇게 하면 서버는 요청마다 사용자를 식별하게 되며, 사용자의 권한에 따라 유연한 응답을 제공할 수 있습니다.
<상세>
- 사용자가 쿠키를 설정한 웹사이트에만 쿠키를 보낼 수 있다!
- 같은 루트 도메인들 사이에서는 쿠키가 공유될 수 있다! ex) mail.google.com, calendar.google.com
- 서버가 보낸 쿠키의 저장 및 재전송은 모두 브라우저에서 자동으로 이루어진다! -> 클라이언트 단에서 편안한 유저 기능 구현 가능
쿠키의 보안 설정
웹에서 인증 정보는 매우 중요합니다. 따라서 쿠키를 사용할 때는 여러가지 보안 설정들을 고려해야합니다.
- Secure
- 이 설정은 HTTPS를 사용하는 사이트에서만 쿠키를 전송할 수 있게 합니다.
- HTTPS는 항상 요청과 응답을 암호화하기에 누군가 정보를 가로챘을 때 유출 위험을 줄일 수 있습니다.
- 이를 통해 중간자 공격(man-in-the-middle attack)을 예방하여, 쿠키의 내용이 외부에 노출되는 것을 방지할 수 있습니다.
- HttpOnly
- 이 설정은 클라이언트 단에서 자바스크립트를 통해 쿠키에 접근할 수 없도록 합니다.
- 오직 요청만 가능하게 하여 프론트 단에서 내제된 코드 수정 위험 자체를 막습니다.
- SameSite
- 이 설정은 사이트 간 요청 공격(CSRF)을 방지하는 데 도움이 됩니다.
- `Strict` 설정은 다른 도메인의 요청에서 쿠키를 완전히 차단합니다. 반면, `Lax` 설정은 이메일과 같이 사용자가 다른 사이트에서 링크를 통해 사이트를 직접 방문할 경우에는 쿠키를 포함시키지만, 직접 방문이 아닌 다른 사이트에서 API 요청 등을 할 경우에는 쿠키를 포함시키지 않습니다.
사용자는 정상적으로 사용하지만 악의적인 사이트에서의 공격이 있을 수 있습니다. 인스타그램이 쿠키인증을 통해 사용자를 식별한다고 가정해보겠습니다. 그러면 브라우저에는 인스타그램 쿠키 인증서가 저장되어 있을 것입니다. 이때 사용자가 실수로 어떤 악의적인 사이트에 접근을 하였고, 이 사이트는 클릭을 하면 인스타그램에 글을 게시하는 API를 호출합니다.
문제는 이 요청은 인스타그램으로 가기 때문에 브라우저에서는 사용자의 쿠키를 같이 보내고, 인스타그램에서는 사용자가 보낸 정상적인 요청으로 판별한다는 것입니다. 그러면 내 계정에 이상한 광고글이 올라올 수도 있습니다. 이를 CSRF 이라고 합니다.
{
Set-Cookie: {cookie_name}={cookie_value};
expires=Mon, 18 Sep 2023 17:05:11 GMT;
HttpOnly;
Max-Age=2592000;
Path=/;
SameSite=Lax;
Secure;
HttpOnly;
SameSite=Lax;
}
수동으로 인증을 관리하는 방법
일반적으로 서버는 `Set-Cookie` 헤더를 통해 자동으로 인증을 관리한다. 하지만 경우에 따라서는 수동으로 인증을 관리하고 싶을 수 있다.
- 서버는 인증서를 생성하고 이를 응답 바디에 포함시켜 클라이언트에게 전송한다.
- 클라이언트는 자바스크립트를 사용하여 이 인증서를 쿠키나 로컬 스토리지에 저장한다. 여기서 쿠키는 단순한 저장소로서의 기능만을 수행한다.
- 요청을 보낼 때, 클라이언트는 저장된 인증서를 직접 `Authorization` 헤더에 첨부하여 서버에게 전송한다.
수동으로 인증을 관리하면 분명 더 귀찮고 더 많은 코드를 작성해야하는 단점이 있지만, 특정 리퀘스트에 인증을 붙일지 안 붙일지 선택할 수 있어 보안에 유리하고, 서로 다른 루트 도메인 사이에서도 인증이 가능하다는 장점이 있습니다.
인증서의 종류
세션 인증
서버가 각각의 방문자에 대한 기록을 세션 저장소에 저장하는 방식입니다.
- 클라이언트가 서버에 접속하면, 서버는 클라이언트의 id, ip, 방문 시각, 브라우저 정보, userID 등을 세션 저장소에 기록합니다.
- 클라이언트에서 서버측에 세션 id값만 보내주면, 서버는 이를 저장소와 대조하여 첫방문인지, 만료된 세션인지, 어떠한 유저가 방문했는지 등을 확인할 수 있습니다.
토큰 인증
유저 정보를 암호화한 문자열을 토큰으로 사용하는 방식. 서버는 유저의 상세 정보를 별도로 저장하거나 조회할 필요가 없습니다.
- 서버는 유저 정보를 암호화하여 토큰으로 생성하고, 이를 클라이언트에게 전송한다.
- 클라이언트는 이 토큰을 포함하여 서버에 요청을 보낸다.
- 서버는 받은 토큰을 복호화하여 유저 정보를 확인한다.
- 토큰은 주로 응답 바디나 `Authorization` 헤더를 통해 주고받는다.
- 로그아웃 시, 클라이언트는 단순히 토큰을 삭제하면 된다.
<보안 유의사항>
쿠키나 로컬 스토리지에 민감한 정보(예: 비밀번호)는 절대로 저장하지 않아야 한다!
'웹개발' 카테고리의 다른 글
스프링부트 프로젝트에 Spotless 적용하기 (0) | 2023.10.16 |
---|---|
TDD (0) | 2023.09.26 |
@ResponseStatus를 이용하여 커스텀 예외를 만드는 방법 (0) | 2023.09.02 |
타임리프를 통한 템플릿 상속 (0) | 2023.08.12 |
서비스(Service) (0) | 2023.08.08 |