로그인관련 쿠키 및 세션 정리
1. 간단한 쿠키 정리
1-1. 쿠키란 무엇인가?
<위키백과>
쿠키(cookie)란 하이퍼 텍스트의 기록서(HTTP)의 일종으로서 인터넷 사용자가 어떠한 웹사이트를 방문할 경우 그 사이트가 사용하고 있는 서버를 통해 인터넷 사용자의 컴퓨터에 설치되는 작은 기록 정보 파일을 일컫는다. HTTP 쿠키, 웹 쿠키, 브라우저 쿠키라고도 한다. 이 기록 파일에 담긴 정보는 인터넷 사용자가 같은 웹사이트를 방문할 때마다 읽히고 수시로 새로운 정보로 바뀐다.
위의 내용대로 쿠키는 웹브라우저가 보관하는 데이터로서 웹 서버에 요청을 보낼 때 쿠키를 함께 전송하고 웹 서버는 브라우저가 전송한 쿠키를 이용해서 데이터를 읽을 수 있다.
1-2. 쿠키 종류
- Session Cookie : 보통 만료시간(Expire date) 설정하고 메모리에만 저장되며 브라우저 종료 시 쿠키를 삭제한다.
- Persistent Cookie : 장기간 유지되는 쿠키파일로 저장되어 브라우저 종료와 관계없이 사용한다.
- Secure Cookie : HTTPS에서만 사용, 쿠키 정보가 암호화되어 전송한다.
- Third-Party Cookie : 방문한 도메인과 다른 도메인의 쿠키, 광고 배너 등을 관리할 때 유입 경로를 추적하기 위해 사용한다.
1-3. 쿠키 단점
- 쿠키에 대한 정보를 매 헤더에 추가하여 보내기 때문에 상당한 트래픽을 발생시킨다.
- 결제 정보 등을 쿠키에 저장하였을 때 쿠키가 유출되면 보안에 대한 문제점도 발생할 수 있다.
2. 쿠키 객체
2-1. Cookie 클래스를 통한 쿠키 생성
Cookie cookie = new Cookie("cookieId", String.valueOf(member.getId()));
//HttpServletResponse에 쿠키 추가하기
response.addCookie(cookie);
브라우저는 이 쿠키를 만들어준 서버에게 다시 요청을 보내게 될 때에 자동으로 해당 쿠키들을 같이 보낸다.
서버는 요청에서 전달된 쿠키를 읽어서 사용을 하게 된다.
2-2. 브라우저가 보낸 Cookie 정보 확인
Cookie[] cookies = request.getCookies();
여러 개의 쿠키를 배열로 받을 수 있으며 쿠키 값이 없으면 null이 반환된다.
Cookie가 가지고 있는 getName()과 getValue()를 이용해서 원하는 쿠키 정보를 찾을 수 있다.
2-3. Cookie 클래스를 통한 쿠키 삭제
Cookie cookie = new Cookie("cookieId", null);
//쿠키 유효기간 설정
cookie.setMaxAge(0);
//HttpServletResponse에 쿠키 추가하기
response.addCookie(cookie);
쿠키의 관리는 브라우저가 하기 때문에 삭제를 할 수 있는 명령어가 따로 없으며 maxAge가 0인 쿠키를 전송하게 되면
상태의 유지시간이 0인 쿠키가 생성이 되고 같은 이름의 다른 쿠키가 들어오게 되면 브라우저는 쿠키를 교체하게 된다.
유지시간이 0이므로 교체된 쿠키는 삭제된다.
Controller에서 로그인 시에 쿠키를 생성해 주면
Response Headers에 쿠키가 들어가 있는 것을 확인할 수 있다.
다른 확인 방법으로는 개발자 도구의 application에 Cookies 부분에서도 확인할 수 있다.
2-4. 보안 문제점과 개선 방향
개발자 도구로 접근해서 쿠키의 Name과 Value의 값 등을 확인할 수 있고 변경까지 가능하기 때문에 만약에 해커가 쿠키의 정보를 변경하게 되면 다른 사용자의 아이디로 로그인이 가능해지므로 보안상 매우 취약하며 고객의 중요한 개인 정보를 훔쳐갈 수 있으므로 악의적인 시도가 계속될 수 있다.
그러므로 쿠키의 정보를 노출하지 않으면서 예측이 불가능한 임의의 랜덤 값을 노출해서 악의적인 시도를 할 수 없도록 막아야 하고 랜덤 값은 시간이 지나면 사용할 수 없도록 만료시간을 짧게 유지해야 한다.
서블릿은 세션을 위해 HttpSession 이라는 기능을 제공하는데, 지금까지 나온 문제들을 해결해준다.
3. 세션 사용
3-1. 세션의 동작
<유저가 로그인 시도시>
아이디, 비번 클릭 시 -> 서버에서 유저 확인 시 -> 세션 저장소 -> 쿠키로 랜덤 값을 브라우저로 넘겨줌
-> 쿠키 저장소에 랜덤 값이 저장됨
회원정보는 브라우저로 넘어가지 않고 랜덤 값만 넘어가게 된다.
<로그인된 유저가 다시 사이트 접속 시>
브라우저에서 쿠키(랜덤 값)를 보내면 -> 세션 저장소에서 확인하고 서버로 넘겨줌 -> 서버에서 확인
위와 같이 세션을 통한 방식을 이용하면 java.util.UUID를 이용해서 개인정보를 보호할 수가 있다.
3-2. HttpSession 인터페이스란 ( 개발새발님 자료 참고 https://gbsb.tistory.com/81 )
HttpSession 인터페이스는 둘 이상의 page request에서 사용자를 식별하거나, 웹 사이트를 방문하고 해당 사용자에 대한 정보를 저장하는 방법을 제공한다.
Servlet container는 HttpSession를 사용하여 HTTP client - HTTP server 간의 세션을 생성한다. 이때, 세션은 한 명의 사용자에 해당한다. 서버는 Cookie, rewriting URL와 같은 방법으로 세션을 유지하면서 관리할 수 있다. 객체를 세션에 바인딩하여 사용자 정보를 유지할 수 있다.
- HttpSession's setAttribute("Key", Value)
- "Key"를 사용하여 객체를 세션에 바인딩한다.
- Value는 값으로 들어올 자료형을 예측할 수 없기에 Object형으로 업 캐스팅하여 모두 받아낸다.
- HttpSession's getAttribute("Key")
- "Key"로 바인딩된 객체를 돌려주고, "Key"로 바인딩된 객체가 없다면 null를 돌려준다.
- Value는 세션을 저장할 때 Object형으로 업 캐스팅을 했으므로, 가져올 땐 원래대로 다운 캐스팅해야 한다.
- HttpServletRequest's getSession(true)
- 이미 세션이 있다면 그 세션을 돌려주고, 세션이 없으면 새로운 세션을 생성한다.
- request.getSession()로 쓸 수 있다.
- HttpServletRequest's getSession(false)
- 이미 세션이 있다면 그 세션을 돌려주고, 세션이 없으면 null을 돌려준다.
3-3. HttpSession 인터페이스 사용
< 세션에 로그인 회원정보 보관 >
// default=true
// getSession(true) 시 : 세션이 있으면 세션 반환, 없으면 신규 세션을 생성
// getSession(false) 시 : 기존 세션이 없으면 세션을 생성하지 않음
//
HttpSession session = request.getSession();
//세션에 로그인 회원 정보 보관
// // "sessionKey"로 memberVO를 세션에 바인딩한다.
session.setAttribute(sessionKey, memberVO);
로그인 이후에 개발자 도구를 확인해 보면
JSESSIONID 이라는 쿠키가 생성된 것을 확인할 수 있다.
예측이 불가능한 임의의 랜덤 값이므로 지금까지 나온 문제들을 해결해준다.
< 세션 만료 >
//세션 만료이므로 false : 세션이 없으면 재생성 X
HttpSession session = request.getSession(false);
if(session != null){
session.invalidate();//세션 삭제
}
session.invalidate()를 사용하면 세션의 정보는 모두 사라진다.
<세션 시간 제거 >
session.setMaxInactiveInterval(30*60); // 30분
브라우저에서 30분 동안 요청이 없으면 세션을 제거한다.
3-4. 세션을 사용하는 게 보안상 좋지만 쿠키를 사용하는 이유
세션은 서버에 데이터를 저장하기에 서버의 자원을 사용하기 때문에 메모리에 부담을 줄 수 있기 때문에 세션과 쿠키를 상황에 맞게 사용하는 것이 중요하다.