FireDrago
[Spring] 로그인 쿠키와 세션 본문
HTTP는 무상태(Stateless)의 특징을 가진다.
응답 - 요청의 사이클이 한번 돌면 더이상 연결을 유지하지 않는다.
그렇다면 우리는 어떻게 로그인 한번으로 계속 로그인 상태를 유지 할 수 있는 걸까?
1. 쿠키

클라이언트가 서버에게 로그인 요청을 보냈다고 생각해보자, 서버에서는 유저의 로그인을 확인했다.
그럼 서버는 클라이언트에게 '쿠키'를 사용하여 로그인 상태를 유지 할 수 있을 것이다.
쿠키를 전달받은 클라이언트는 쿠키가 유효한 기간동안 모든 요청에 쿠키를 함께 전달한다.
서버는 전달받은 쿠키를 통해 로그인 상태를 유지할 수 있게된다.
쿠키의 종류
- 세션 쿠키 : 유효기간 지정하지 않은 쿠키, 브라우저 종료시 까지 유효하다.
- 영속 쿠키 : 유효기간이 지정된 쿠키, 유효기간 까지 유효하다.

로그인을 담당하는 메서드 login 을 살펴보자 로그인이 성공한 경우 쿠키를 생성하고 HttpServletResponse 객체에
쿠키를 담아서 응답에 보낸다. 이렇게 되면 이후의 클라이언트의 모든 요청은 쿠키의 유효기간 동안 쿠키가 함께 전송된다.
<쿠키의 보안문제>
문제는 쿠키로 로그인 정보를 보냈을때 보안문제가 발생할 수 있다는 점이다.
1. 쿠키는 클라이언트가 변경할 수 있다.
- 클라이언트가 쿠키의 memberId를 변경하여 다른 사람의 계정으로 접속 할 수 있다
2. 쿠키에 개인정보가 있을경우, 유출 될 수 있다.
3. 해커가 탈취하면 계속 사용이 가능하다. (쿠키 유효기간 동안)
쿠키에 사용자 별로 예측 불가능한 임의의 토큰(랜덤 값)을 노출하고,
서버에서 토큰과 사용자 id를 매핑해서 인식한다. 그리고 서버에서 토큰을 관리한다.
토큰은 해커가 임의의 값을 넣어도 찾을 수 없도록 예상 불가능 해야 한다.
해커가 토큰을 털어가도 시간이 지나면 사용할 수 없도록 서버에서 해당 토큰의 만료시간을 짧게 유지한다. (30분)
또는 해킹이 의심되는 경우 서버에서 해당 토큰을 강제로 제거하면 된다.
이를 위해 세션이 필요하다.
2. 세션

세션은 로그인이 확인 된 경우 랜덤한 세션ID(UUID)를 생성한다.
생성된 세션 ID와 세션에 보관할 값( 유저정보 )을 서버의 세션 저장소에 보관한다.
서버는 클라이언트에 mySessionId 라는 이름으로 세션ID 만 쿠키에 담아서 전달한다.
이렇게 하면, 쿠키가 변조될 경우 제대로 작동할 수 없고, 개인정보가 담기지 않았으므로 유출의 위험도 없다.
서버가 30분 마다 세션ID를 초기화 하면 해커가 계속 사용하기도 힘들어진다.

1. 세션 생성 (createSession) : 랜덤 sessionId를 생성하고, 객체를 세션에 저장한다. 쿠키에 세션명을 담아 전달한다
2. 세션 조회 (getSession) : 요청에서 쿠키를 조회한뒤, 세션과 비교하여 가져온다.
3. 세션 만료 (expire) : 요청에서 쿠키를 조회한뒤, 세션에서 객체를 지운다.
세션의 원리를 알아보았으니 스프링에서 기본제공하는 Session 기능을 사용해보자 원리는 위의 코드와 같다.
더 많은 기능과 편리함을 제공할 뿐이다.
<HttpSession>

// 로그인 성공 밑을 보면 request.getSession( )을 통해 HttpSession을 생성한다.
getSession(false) : 세션이 없으면 null 반환
getSession(true) : 기본값 (생략가능) 세션이 없으면 세션 생성후 반환
세션 데이터의 저장은 setAttribute(키, value) 형태로 저장한다. 원리는 위 코드와 비슷하다.

getSession(false) 를통해 null이 올 수 도 있다. null이 오면 일반 홈페이지, 세션에 저장된 값이 있고
쿠키의 세션아이디와 일치하면 로그인 홈페이지로 보낸다.
<@SessionAttribute>
스프링은 더 편리하게 Session을 사용할수 있도록 애너테이션을 지원한다.

@SessionAttribute (name = 'key값', required = true/false) 로 더 편리하게 세션값을 확인할 수 있다.
required 속성은 HttpSession의 getsession(true/false) 와 같은 기능을 한다.
<세션 타임아웃 설정>
글로벌 설정 : application.properties 파일에 server.servlet.session.timeout=60 (분단위) 설정한다.
모든 세션이 1분 (60초)이후에 지워진다. HttpSession이 제공하는 기능이다.
개별 설정 : 자바코드에서 session.setMaxInactiveInterval(1800); 설정한다.
특정 세션만 시간을 설정할 수 도 있다.
'프로그래밍 > Spring' 카테고리의 다른 글
| [Spring] 스프링 예외처리와 오류페이지 (0) | 2024.02.17 |
|---|---|
| [Spring] 서블릿 필터와 스프링 인터셉터 (0) | 2024.02.15 |
| [Spring] Bean Validation (0) | 2024.02.12 |
| [Spring] 검증처리 (0) | 2024.02.09 |
| [Spring] HttpMessageConverter (0) | 2024.02.01 |
