인증을 구현하다가 문득 로그아웃은 어떤 http 메서드를 사용해야하는지에 대해 의문이 들었다.
로그인의 경우 지금까지 자연스럽게 POST 메서드로 요청을 받도록 구현해왔지만, 로그아웃의 경우 GET으로 작성하면서도 맞는건지 확신이 들지 않아서 찾아봤다.
결론부터 말하자면, 로그인의 경우
POST
가 더 나은 방법이라고 할 수 있다.
로그인의 경우 비밀번호라는 민감한 정보가 들어있기 때문에, 쿼리 스트링으로 노출되는 GET 방식보다는 POST 방식으로 요청을 보내는 것이 안전하다
라는 것 정도는 알고 있었다.
더 구체적인 이유를 찾아본 결과,
우선 GET 요청
은 서버 데이터의 상태를 변경하지 않기 때문에 쿼리를 적극적으로 캐싱할 수 있어 비밀번호와 같은 정보를 쿼리에 담아 보내면 보안에 취약할 수 있다.
반면 POST 요청
은 서버의 상태를 변경시키고 동일한 응답을 주며, 서버를 동일한 상태로 유지하기위해 캐싱을 하지 않기 때문에 GET보다는 안전하다고 볼 수 있다.
하지만, GET, POST 모두 HTTP protocol을 사용하면 내부 데이터는 패킷으로 전송되기에 다 노출된다.
결국 HTTPS
나 전송 구간에 암호화를 하는 것이 중요하다. 로그인 시 POST를 사용하면 body에 담겨서 보내지는데 이것을 HTTPS를 적용하면 암호화가 된다.
로그아웃의 경우 POST, GET, DELETE 등 여러가지 의견이 있었지만, 여러 의견을 종합해본 결과 POST를 사용하기로 결정했다.
GET 요청을 사용해도 된다는 사람들의 입장은 서버 측에 요청할 때 특별한 데이터를 담지 않기 때문에 GET을 사용해도 무방하다는 것이다.
하지만, 아래 자료는 이에 반대하는 입장, 즉 GET을 사용했을 때 나타날 수 있는 부작용에 대해 설명하고 있다.
위 글은 서버쪽으로 요청을 보낼 때 특별한 데이터를 담지도 않고, 단순하기 때문에 GET 메서드를 사용할 수도 있고 GET 메서드로 동작할 수도 있지만, 부작용이 있을 수 있으며, 해당 부작용은 prefetch
라는 기술과 관련이 있다는 내용이다.
여기서
prefetch
란, 사용자를 위해 GET 링크를 미리 가져와, 사용자가 해당 링크를 클릭했을 때 즉시 제공함으로써 페이지 로딩 시간을 줄이는 프로세스이다.
이때 로그아웃을 GET 요청으로 구현하게 되면, 페이지에서 링크를 미리 가져오려고 시도하는 동안 실수로 사용자를 로그아웃 시킬 수 있다.
prefetch와 같은 기술은 GET 링크가 콘텐츠를 반환하기 위해서 존재한다고 가정하기 때문
이다.
HTTP/1.1 RFC
또한 GET 메서드는 컨텐츠를 반환하는 용도로만 사용해야 하며 사용자는 GET 요청의 부작용에 대해 책임을 질 수 없다고 분명히 명시하고 있기 때문에, 가능하면 이 권장 사항을 따라야 한다는 것이다.
결론적으로 로그아웃 요청도 서버에 세션/토큰을 처리하는 로그아웃 프로세스를 요청하는 것이므로 POST 요청을 사용해야 하며,
GET 요청을 사용하면 안되는 이유는 prefetch와 같은 기술에 영향을 받아 비정상적으로 동작할 수 있으며, GET 요청은 본질적으로 컨텐츠 반환에 사용되어야 하기 때문이다.
+참고로,
Spring Security
는 기본적으로 로그아웃 요청이 POST 메서드여야 하지만, CSRF 보호를 비활성화하는 경우 GET 메서드로 로그아웃 요청을 사용하도록 할 수 있다.