본문 바로가기
JAVA Spring

로그인 처리 - 쿠키와 세션

by ppirae 2022. 6. 17.

스프링 프레임워크 기말고사 프로젝트를 진행하면서

쿠키를 사용해서 로그인을 유지할 수 있었다. 그런데 쿠키에는 심각한 보안문제가 있다.

 

보안문제

  • 쿠키값은 임의로 변경 가능
  • 쿠키에 보관된 정보는 훔쳐갈 수 있음
  • 해커가 쿠키를 훔쳐가면 평생 사용 가능

 

대안

  • 쿠키에 중요한 값을 노출하지 않고, 사용자 별로 예측 불가능한 임의의 토큰(랜덤 값)을 노출하고, 서버에서 토큰과 사용자 id를 매핑해서 인식한다. 그리고 서버에서 토큰을 관리한다.
  • 토큰은 해커가 임의의 값을 넣어도 찾을 수 없도록 예상 불가능 해야 한다.
  • 해커가 토큰을 털어가도 시간이 지나면 사용할 수 없도록 서버에서 해당 토큰의 만료시간을 짧게(예: 30분) 유지한다.

이러한 보안책들을 한번에 해결할 수 있는 방법이 서버 세션이다.

 

세션 ID를 추정이 불가능한 UUID로 생성해서

생성된 세션 ID와 세션에 보관할 값을 서버의 세션 보관소에 저장한다.

세션 ID만 쿠키를 통해 클라이언트에 전달한다

 

중요

  • 회원과 관련된 정보는 전혀 클라이언트에 전달하지 않는다
  • 오직 추정 불가능한 세션 ID만 쿠키를 통해 클라이언트에 전달

세션 직접 만들기

세션을 직접 만드는 도중 sessionTest를 진행하는데 

HttpServletResponse는 interface라서 테스트가 쉽지 않다.

이럴 때 스프링에서 제공하는 MockHttpServletResponse를 이용하여 테스트를 진행할 수 있다.

 

직접 세션을  개발해봤는데 매우 불편하다.

그래서 서블릿도 세션 개념을 지원한다.

서블릿이 공식 지원하는 세션은 직접 만든 세션과 동작 방식이 거의 같다.

추가로 세션을 일정시간 사용하지 않으면 해당 세션을 삭제하는 기능을 제공한다.


서블릿 HTTP 세션

서블릿을 통해 HttpSession을 생성하면 다음과 같은 쿠키를 생성한다. 쿠키이름이 JSESSIONID이고, 

값은 추정 불가능한 랜덤값이다

Cookie: JSESSIONID=5B78E23B513F50164D6FDD8C97B0AD05 (이런 식)

 

세션 생성과 조회

세션을 생성하려면 request.getSession을 사용하면 된다.

request.getSession(true) -> 세션이 있으면 기존 세션, 없으면 새로운 세션 생성 후 반환

request.getSession(false) -> 세션이 있으면 기존 세션, 없으면 null 반환

 

session.invaidate() : 세션을 제거

 

@SessionAttribute

스프링은 세션을 더 편리하게 사용할 수 있도록 @SessionAttribute 을 지원한다.

 

이미 로그인 된 사용자를 찾을 때는 다음과 같이 사용하면 된다. 참고로 이 기능은 세션을 생성하지 않는다. @SessionAttribute(name = "loginMember", required = false) Member loginMember


세션 타임아웃 설정

세션은 사용자가 로그아웃을 직접 호출해서 session.invalidate() 가 호출 되는 경우에 삭제된다. 그런데 대부분의 사용자는 로그아웃을 선택하지 않고, 그냥 웹 브라우저를 종료한다. 문제는 HTTP가 비 연결성(ConnectionLess)이므로 서버 입장에서는 해당 사용자가 웹 브라우저를 종료한 것인지 아닌지를 인식할 수 없다. 따라서 서버에서 세션 데이터를 언제 삭제해야 하는지 판단하기가 어렵다.

 

대규모 서비스의 경우 세션을 무한정 보관하면 메모리와 자원에 과부하가 올수 있기때문에 세션의 종료가 필요하다.

 

세션의 종료 시점

사용자가 서버에 최근에 요청한 시간을 기준으로 30분을 정도를 유지해주는 것이 좋은 방안 중 하나이다.

 

세션 타임아웃 설정

스프링 부트로 글로벌 설정하고

application.properties에

server.sevelet.session.timeout = sss, 기본은 1800(30분) 을 추가한다.

 

특정 세션 단위로 시간 설정은

session.setMaxInactiveInterval(sss);

 

세션 타임아웃 발생

세션의 타임아웃 시간은 해당 세션과 관련된 JSESSIONID 를 전달하는 HTTP 요청이 있으면 현재 시간으로 다시 초기화 된다. 이렇게 초기화 되면 세션 타임아웃으로 설정한 시간동안 세션을 추가로 사용할 수 있다. session.getLastAccessedTime() : 최근 세션 접근 시간 LastAccessedTime 이후로 timeout 시간이 지나면, WAS가 내부에서 해당 세션을 제거한다.

 

실무에서 조심할 점은 세션에는 최소한의 데이터만 보관해야 한다.

데이터 * 사용자 수로 메모리 사용량이 급격하게 늘어나기 때문이다.

또 세션의 시간을 적당히 해야 메모리 사용을 조절할 수 있다.


인프런 김영한님의 스프링 MVC 2편을 듣고 작성한 글입니다.

https://inf.run/oKtV

 

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의

웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있

www.inflearn.com


혹시 UUID가 겹치는 경우가 생기지 않을까 궁금해서 찾아보았다.

koreanhole님의 글입니다.

https://velog.io/@koreanhole/UUID%EA%B0%80-%EA%B2%B9%EC%B9%98%EB%A9%B4-%EC%96%B4%EC%A9%8C%EC%A7%80

 

UUID가 겹치면 어쩌지?

최근 UOS공지사항 앱의 백엔드 시스템을 교체하는 작업을 하고 있습니다.기존 Firebase의 Firestore를 사용하고 있었는데 이번에 새롭게 Nestjs로 서버를 작성하는 중입니다.UOS공지사항의 서버에는 총

velog.io

 

'JAVA Spring' 카테고리의 다른 글

스프링 타입 컨버터  (0) 2022.06.25
로그인 처리 - 필터, 인터셉터  (0) 2022.06.18
검증 - Bean Validation  (0) 2022.05.29
메시지, 국제화  (0) 2022.05.26
타임리프 - 기본기능(2)  (0) 2022.05.25

댓글