쿠키
- 종류
- 영속 쿠키
- 만료 날짜를 입력하면 해당 날짜까지 유지
- 세션 쿠키
- 만료 날짜를 생략하면 브라우저 종료시 까지만 유지
- 로그인 경우 주로적용
- 영속 쿠키
- 보안 문제
- 쿠키 값은 임의로 변경할 수 있어서, 단순한 값으로 쿠키 적용시 보안상 큰 문제가 잇다.
- 쿠키에 보관된 정보는 훔쳐갈 수 있다. (로컬PC, 네트워크 전송 구간)
- 개인정보나, 신용카드 정보가 있다면 사용자의 금전적 피해까지 입힐 수 있다.
- 한번 탈취된 쿠키는 평생 사용 가능하다.
- 대안
- 쿠키에 중요한 값을 노출하지 않고, 사용자 별로 예측 불가능한 임의의 토큰(랜덤 값)을 노출하고,
서버에서 토큰과 사용자 id를 매핑해서 인식한다, 그리고 서버에서 토큰을 관리한다. - 토큰은 해커가 임의의 값을 넣어도 찾을 수 없도록 예상 불가능 해야 한다.
- 해커가 토큰을 털어가도 시간이 지나면 사용할 수 없도록 서버에서 해당 토큰 만료시간을 짧게 유지한다.
- 해킹이 의심되는 경우 해당 토큰을 강제로 제거
- 쿠키에 중요한 값을 노출하지 않고, 사용자 별로 예측 불가능한 임의의 토큰(랜덤 값)을 노출하고,
쿠키+세션 적용
- 앞서 쿠키에 중요한 정보를 보관하는 방법은 여러가지 보안 이슈가 있었다.
- 이 문제를 해결하려면 결국 중요한 정보를 모두 서버에 저장해야 한다.
- 그리고 클라이언트와 서버는 추정 불가능한 임의의 식별자 값으로 연결해야 한다.
- 이렇게 서버에 중요한 정보를 보관하고 연결을 유지하는 방법을 세션이라 한다.
- 세션 ID를 생성하는데, 추정 불가능해야 한다. - 자바에서 UUID 생성 지원
- 서버에서는 세션 테이블(UUID, 정보)을 만든 후 쿠키에 UUID를 보낸다.
- 클라이언트는 요청시 항상 mySessionId 쿠키를 전달한다.
- 서버에서는 클라이언트가 전달한 mySessionId 쿠키 정보로 세션 저장소를 조회해서 로그인시 보관한 세션 정보를 사용한다.
- 세션을 사용해서 서버에서 중요한 정보를 관리하게 되었다. 덕분에 다음과 같은 보안 문제들을 해결할 수 있다.
- 쿠키 값을 변조 가능
- 예상 불가능한 복잡한 세션ID를 사용한다.
- 쿠키에 보관하는 정보는 클라이언트 해킹시 털릴 가능성이 있다.
- 세션Id가 털려도 여기에는 중요한 정보가 없다.
- 쿠키 탈취 후 사용
- 해커가 토큰을 털어가도 시간이 지나면 사용할 수 없도록 서버에서 세션의 만료시간을 짧게 (예: 30분) 유지한다.
또는 해킹이 의심되는 경우 서버에서 해당 세션을 강제로 제거하면 된다.
- 해커가 토큰을 털어가도 시간이 지나면 사용할 수 없도록 서버에서 세션의 만료시간을 짧게 (예: 30분) 유지한다.
- 쿠키 값을 변조 가능
작동 순서
- 처음 로그인 시 세션ID와 쿠키를 만들어 클라이언트에게 쿠키에 보낸다.
- 쿠키를 가지고 있는 사용자라면 해당 쿠키를 조회한다.
- 세션에 있으면 로그인 처리!
HttpSeesion의 쿠키 이름은 JSESSIONID이고,
생성할때는
- request.getSession(true) - default
- 세션이 있으면 기존 세션 반환
- 세션이 없으면 세션을 생성해서 반환
- request.getSession(false)
- 세션이 있으면 기존 세션 반환
- 세션이 없으면 생성하지 않고, null반환
를 사용하고 신규 세션에 세팅할때는
Session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
세션에 데이터를 보관하는 방법은 request.setAttribute(..) 와 비슷하다. 하나의 세션에 여러 값을 저장할 수
있다.
제거 : session.invalidate() :
스프링의 세션 편의 사용
기존
@GetMapping("/")
public String homeLoginV3(HttpServletRequest request, Model model) {
//세션이 없으면 home
HttpSession session = request.getSession(false);
if (session == null) {
return "home";
}
Member loginMember = (Member)
session.getAttribute(SessionConst.LOGIN_MEMBER);
//세션에 회원 데이터가 없으면 home
if (loginMember == null) {
return "home";
}
//세션이 유지되면 로그인으로 이동
model.addAttribute("member", loginMember);
return "loginHome";
}
변경 - @SessionAttribute 사용
@GetMapping("/")
public String homeLoginV3Spring(
@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false)
Member loginMember,
Model model) {
//세션에 회원 데이터가 없으면 home
if (loginMember == null) {
return "home";
}
//세션이 유지되면 로그인으로 이동
model.addAttribute("member", loginMember);
return "loginHome";
}
TrackinModes
쿠키-세션이 적용된 상태에서 서버를 처음 시작할 시 URL뒤에 ;jsessionid=~~~가 붙는데
이는 쿠키를 지원하지 않는 웹브라우저를 위해 사용되는 것이므로
application.propertis에
server.servlet.session.tracking-modes=cookie 를 적용하면 된다.
spring.mvc.pathmatch.matching-strategy=ant_path_matcher - jsessionid가 필요할 경우 사용
세션의 타임아웃과 필요성
- 세션은 사용자가 로그아웃을 직접 호출해서 invalidate()가 호출 되는 경우에 삭제된다.
- 그런데! 사용자 대부분은 로그아웃을 누르지 않는다.
- 이때, 서버 입장에서는 브라우저가 닫힌 상태인걸 모른다.
- 이렇게 되면, 세션이 무한정으로 쌓인다.
- 그래서 종료 시점을 설정해야하는데 기준을 어떻게 설정해야 좋을까?
- 단순한 방법
- 생성 시점 30분 이상
- 글로벌 : application.properties에 server.servlet.session.timeout=60: 60초 (default:1800)
- 특정세션 : session.setMaxInactiveInterval(60);
- 단점 : 계속 사용 중인 사용자도 30분이 지나면 로그아웃 됌
- 이로인해, 30분마다 로그인을 해야하는 번거로움이 생김
- 대안 : 사용자가 마지막 요청한 시간 기준으로 30분 후 세션 삭제
- 사용법: 시간 설정해두면 스프링에서 자동으로 연장해줌
- LastAccesedTime 이후로 timeout 시간이 지나면 WAS가 내부에서 해당 세션 제거
- 단순한 방법
- 현재 문제점 : URL만 알면 어디든 접속 가능함 - 필터와 인터셉터 사용
출처: https://tan-sog.tistory.com/90
'Spring' 카테고리의 다른 글
[Spring] ArgumentResolver (0) | 2024.05.25 |
---|---|
[Spring] 필터와 인터셉터 (0) | 2024.05.25 |
[Spring] Bean Validation (0) | 2024.05.16 |
[Spring] 검증(Validation) (1) | 2024.05.15 |
[Spring] 메시지와 국제화 (0) | 2024.05.15 |