(2) 로그인 처리 - 세션

CJY·2023년 4월 6일
0

스프링

목록 보기
9/14

이전에 알아본 쿠키만을 이용한 로그인 서비스를 실현하기에는 보안상 많은 문제점들이 있다. 이를 해결하기 위해서는 민감한 정보를 서버측에서 저장해야한다. 그리고 클라이언트와 서버는 추정 불가능한 임의의 식별자값으로 연결해야 한다.

세션

세션은 위에서 말한 방법을 그대로 실현한다.

서버는 로그인한 사용자의 쿠키에 UUID를 보낸다. 앞에서 살펴봤지만 쿠키는 namevalue가 있다. 예를 들어, namemySessionId라고 보낸다면 클라이언트의 쿠키는 아래와 같을 것이다.

Set-Cookie: mySessionId=qweqr-54453d-sfe84f6s-fdf54ef2-...

서버는 이제 고유한 UUID와 회원 객체를 맵핑시켜놓으면 된다.

이제 세션을 사용해서 서버에서 중요한 정보를 관리하게 되었다. 덕분에 다음과 같은 보안 문제들을 해결할 수 있다.

  • 쿠키 값을 변조 가능 \rarr 예상 불가능한 복잡한 세션Id를 사용한다.
  • 쿠키에 보관하는 정보는 클라이언트 해킹시 털릴 가능성이 있다. \rarr 세션Id가 털려도 여기에는 중요한 정보가 없다.
  • 쿠키 탈취 후 사용 \rarr 해커가 토큰을 털어가도 시간이 지나면 사용할 수 없도록 서버에서 세션의 만료시간을 짧게(예: 30분) 유지한다. 또는 해킹이 의심되는 경우 서버에서 해당 세션을 강제로 제거하면 된다

세션은 제법 간단하게 직접 구현할 수도 있지만 서블릿에서 공식 지원하는 세션이 있다.

HttpSession

쿠키 이름이 JSESSIONID이다.

Controller의 구현 함수에서 HttpServletRequest를 파라미터로 받고나서 getSession()을 통해 HttpSession객체를 받을 수 있다. 없다면 새로 생성하게 된다.

public HttpSession getSession(boolean create);

세션의 create 옵션에 대해 알아보자.
HttpServletRequest 인스턴스를 request라고 하면

  • request.getSession(true)
    세션이 있다면 기존 세션을 반환하고, 세션이 없다면 새로운 세션을 생성해서 반환한다.
    참고로 default값은 true이다.
  • request.getSession(false)
    세션이 있으면 기존 세션을 반환한다.
    세션이 없으면 새로운 세션을 생성하지 않는다. null 을 반환한다.
    보통 세션을 찾을 때 false option을 설정한다. 그렇지 않으면 로그인하지 않을 사용자에게 의미없는 세션을 만든다.

세션에 로그인 회원 정보 보관
session.setAttribute("식별자", 회원 객체);
세션에 데이터를 보관하는 방법은 request.setAttribute(..) 와 비슷하다. 하나의 세션에 여러 값을 저장할 수 있다.

session.invalidate() : 세션을 제거한다

session.getAttribute("식별자") : 로그인 시점에 세션에 보관한 회원 객체를 찾는다.

@SessionAttribute

스프링은 세션을 더 편리하게 사용할 수 있도록 @SessionAttribute을 지원한다.
이미 로그인 된 사용자를 찾을 때 사용하면 된다. 참고로 이 기능은 세션을 생성하지 않는다.

@SessionAttribute(name = "loginMember", required = false) Member loginMember

파라미터에서 사용된다.
Member가 회원 클래스이고 loginMember에 세션을 통한 회원의 정보가 담긴다.

TrackingModes

로그인을 처음 시도하면 URL에 jsessionid 를 포함하고 있는 것을 확인할 수 있다.

http://localhost:8080/;jsessionid=118F518B92983F871CF62D09F0DF59F2

쿠키를 지원하지 않는 웹 브라우저가 존재하는데 쿠키 대신 URL을 통해 세션을 유지하는 방법이다. 이 방법은 URLjsessionid를 계속 포함해서 전달해야 한다. 타임리프 같은 템플릿은 엔진을 통해서 링크를 걸면 jsessionidURL에 자동으로 포함해준다. 서버 입장에서 웹 브라우저가 쿠키를 지원하는지 하지 않는지 최초에는 판단하지 못하므로, 쿠키 값도 전달하고, URL에 jsessionid 도 함께 전달한다.

URL 전달 방식을 끄고 항상 쿠키를 통해서만 세션을 유지하고 싶으면 다음 옵션을 넣어주면 된다.

application.properties
server.servlet.session.tracking-modes=cookie

세션 정보

  • sessionId : 세션Id, JSESSIONID 의 값이다. 예) 5a849027-8a5e-4cd3-9d08-4a54d42bc161
  • maxInactiveInterval : 세션의 유효 시간, 예) 1800초, (30분)
  • creationTime : 세션 생성일시
  • lastAccessedTime : 세션과 연결된 사용자가 최근에 서버에 접근한 시간, 클라이언트에서 서버로 sessionId ( JSESSIONID )를 요청한 경우에 갱신된다.
  • isNew : 새로 생성된 세션인지, 아니면 이미 과거에 만들어졌고, 클라이언트에서 서버로
    sessionId ( JSESSIONID )를 요청해서 조회된 세션인지 여부

세션 타임아웃

세션 타임아웃 설정
스프링 부트로 글로벌 설정

application.properties에서
server.servlet.session.timeout=?? : ??초, 기본은 1800(30분)

글로벌 설정은 분 단위로 설정해야 한다. 60(1분), 120(2분), ...

정리

로그인 처리 방법 중 세션에 대해 알아보았다. HttpSession이 기본적으로 제공되고 있어 따로 구현하는 일 없이 사용하면 굉장히 편해보인다. 하지만 세션은 메모리를 사용하는 일이므로 최소한의 정보만을 유지할 필요가 있어보인다. 최근에 JWT에 대해 알게됐는데 이 부분도 깊이있게 공부해봐야겠다.

profile
열심히 성장 중인 백엔드

0개의 댓글