Spring Web MVC - 쿠키(Cookie)

Hallelujah·2024년 11월 25일

Spring

목록 보기
16/22

https://jakarta.ee/specifications/servlet/5.0/apidocs/jakarta/servlet/http/cookie

소스코드

1. 쿠키란?

  • 쿠키(Cookie)는 웹 서버가 클라이언트(브라우저)에 저장하는 작은 데이터 조각입니다.
  • 클라이언트-서버 간 상태 정보를 유지하기 위해 사용됩니다.
  • 브라우저는 서버에서 설정한 쿠키를 저장하고, 이후 동일한 서버로 요청할 때마다 쿠키를 함께 전송합니다.

2. 쿠키의 주요 특징

  • 저장 위치: 클라이언트(브라우저).
  • 전송 방식: HTTP 요청 헤더(Cookie)와 응답 헤더(Set-Cookie)를 통해 서버와 주고받음.
  • 수명:
    • 세션 쿠키: 브라우저를 닫으면 삭제.
    • 영구 쿠키: 만료 시간을 설정하면 브라우저를 닫아도 유지됨.
  • 보안:
    • 클라이언트에 저장되므로 조작 가능성이 있음(HTTPS, HttpOnly로 보안 강화 가능).
  • 용량 제한:
    • 하나의 쿠키 크기는 최대 4KB.
    • 도메인당 최대 20~50개(브라우저에 따라 다름).

3. 쿠키의 동작 방식

3.1 데이터 흐름

  1. 클라이언트가 서버에 요청.
  2. 서버가 응답 헤더에 Set-Cookie를 추가하여 쿠키 전달.
  3. 클라이언트는 쿠키를 저장.
  4. 이후 요청 시 브라우저가 저장된 쿠키를 HTTP 요청 헤더에 추가.
sequenceDiagram
    participant Client as 클라이언트 (브라우저)
    participant Server as 서버
    Client->>Server: HTTP 요청 (로그인)
    Server-->>Client: HTTP 응답 + Set-Cookie (sessionId=abc123)
    Client->>Server: HTTP 요청 + Cookie (sessionId=abc123)
    Server-->>Client: 사용자 상태 확인 및 응답

4. 쿠키 설정

4.1 쿠키 설정 헤더

Set-Cookie: sessionId=abc123; Max-Age=3600; Path=/; HttpOnly; Secure
  • sessionId=abc123: 쿠키 이름과 값.
  • Max-Age=3600: 쿠키의 수명(초 단위).
  • Path=/: 쿠키가 적용될 경로.
  • HttpOnly: JavaScript로 접근 불가, XSS 공격 방지.
  • Secure: HTTPS 연결에서만 전송.
  • 클라이언트가 서버에 요청할 때 쿠키를 함께 전송.
Cookie: sessionId=abc123

4.2 Spring MVC에서 쿠키 설정

쿠키 생성

@GetMapping("/set-cookie")
public ResponseEntity<String> setCookie(HttpServletResponse response) {
    Cookie cookie = new Cookie("username", "홍길동");
    cookie.setMaxAge(7 * 24 * 60 * 60); // 7일 유지
    cookie.setPath("/"); // 모든 경로에서 유효
    cookie.setHttpOnly(true); // JavaScript 접근 불가
    cookie.setSecure(true); // HTTPS에서만 전송
    response.addCookie(cookie);
    return ResponseEntity.ok("Cookie set!");
}

쿠키 읽기

@GetMapping("/get-cookie")
public ResponseEntity<String> getCookie(@CookieValue(value = "username", defaultValue = "Guest") String username) {
    return ResponseEntity.ok("Hello, " + username);
}

모든 쿠키 읽기

@GetMapping("/get-all-cookies")
public ResponseEntity<String> getAllCookies(HttpServletRequest request) {
    Cookie[] cookies = request.getCookies();
    if (cookies != null) {
        for (Cookie cookie : cookies) {
            System.out.println(cookie.getName() + " = " + cookie.getValue());
        }
    }
    return ResponseEntity.ok("Cookies printed in server logs.");
}

쿠키 삭제


쿠키는 클라이언트(브라우저)에 저장된 데이터이므로 삭제하려면 쿠키의 수명을 설정하거나, 서버에서 동일한 이름과 경로로 만료된 쿠키를 설정해야 합니다.

삭제 방법

  1. 만료 시간 설정:
    • Max-Age를 0으로 설정하면 브라우저는 즉시 쿠키를 삭제합니다.
    • Expires를 과거 시간으로 설정하면 삭제됩니다.
  2. 쿠키 경로와 도메인 일치:
    • 삭제하려는 쿠키와 동일한 경로와 도메인으로 설정해야 합니다.

4.2. Spring에서 쿠키 삭제하기

4.2.1 HttpServletResponse로 쿠키 삭제

  • 서버에서 클라이언트에게 만료된 쿠키를 보내도록 설정.
@GetMapping("/delete-cookie")
public ResponseEntity<String> deleteCookie(HttpServletResponse response) {
    Cookie cookie = new Cookie("username", null); // 값은 null로 설정
    cookie.setMaxAge(0); // 즉시 만료
    cookie.setPath("/"); // 경로 일치
    response.addCookie(cookie);
    return ResponseEntity.ok("Cookie deleted");
}

동작 원리

  • 동일한 이름, 경로, 도메인의 쿠키가 브라우저에서 만료되어 삭제됩니다.

4.2.2 HttpServletRequest로 쿠키 확인 후 삭제

  • 요청에서 특정 쿠키를 검색한 후 삭제 쿠키를 생성합니다.
@GetMapping("/delete-specific-cookie")
public ResponseEntity<String> deleteSpecificCookie(HttpServletRequest request, HttpServletResponse response) {
    Cookie[] cookies = request.getCookies();
    if (cookies != null) {
        for (Cookie cookie : cookies) {
            if ("username".equals(cookie.getName())) {
                Cookie deleteCookie = new Cookie("username", null);
                deleteCookie.setMaxAge(0); // 즉시 만료
                deleteCookie.setPath("/");
                response.addCookie(deleteCookie);
            }
        }
    }
    return ResponseEntity.ok("Specific cookie deleted");
}

4.3. JavaScript로 쿠키 삭제

클라이언트 측에서 JavaScript를 사용해 쿠키를 삭제할 수도 있습니다. 단, HttpOnly가 설정된 쿠키는 JavaScript로 삭제할 수 없습니다.

// 쿠키 삭제
document.cookie = "username=; Max-Age=0; path=/;";

쿠키 삭제 시 주의 사항

  1. 경로(Path)와 도메인(Domain):
    • 삭제하려는 쿠키와 동일한 경로와 도메인으로 설정해야 브라우저에서 삭제됩니다.
  2. 보안 속성:
    • HttpOnly, Secure 속성이 설정된 쿠키는 서버에서만 삭제 가능하며, JavaScript로 삭제할 수 없습니다.
  3. 쿠키 존재 여부 확인:
    • 삭제하려는 쿠키가 존재하지 않을 경우에도 서버가 만료된 쿠키를 전송하면 브라우저에서 처리됩니다.

  • 쿠키를 삭제하려면:
    1. Max-Age=0 또는 Expires를 과거로 설정.
    2. 동일한 이름, 경로, 도메인으로 설정.
  • 보안 쿠키 삭제:
    • HttpOnly, Secure 속성이 설정된 쿠키는 서버에서만 삭제 가능.
  • 모든 쿠키 삭제:
    • 서버는 모든 쿠키 이름을 확인 후 개별적으로 삭제해야 함.

5. 쿠키의 사용 사례

  1. 로그인 상태 유지: 세션 ID를 쿠키에 저장.
  2. 사용자 환경 설정: 테마, 언어, 글꼴 크기 등.
  3. 광고 추적: 사용자 방문 기록 저장.
  4. 장바구니: 장바구니 데이터 임시 저장.

6. 쿠키의 보안 문제와 해결

6.1 보안 문제

  1. 가로채기:
    • HTTP를 사용하면 쿠키가 평문으로 전송되어 도청 가능.
  2. 조작 가능성:
    • 클라이언트가 쿠키 값을 임의로 변경 가능.
  3. XSS 공격:
    • 악성 스크립트가 쿠키 값을 읽을 수 있음.

6.2 보안 강화 방법

  1. HTTPS 사용:
    • HTTPS를 통해 쿠키 전송 시 데이터를 암호화.
  2. HttpOnly 설정:
    • JavaScript로 쿠키 접근을 차단.
  3. Secure 설정:
    • HTTPS 연결에서만 쿠키를 전송.
  4. SameSite 설정:
    • 크로스 사이트 요청 위조(CSRF) 방지.
    • 값:
      • Strict: 쿠키는 동일한 사이트에서만 전송.
      • Lax: 대부분의 크로스 사이트 요청에서 쿠키가 전송되지 않음.
      • None: 크로스 사이트 요청에서도 쿠키 전송(단, Secure 필요).
Cookie cookie = new Cookie("sessionId", "abc123");
cookie.setHttpOnly(true);
cookie.setSecure(true);
cookie.setPath("/");
cookie.setMaxAge(3600); // 1시간
response.addCookie(cookie);

7. 쿠키의 단점

  1. 크기 제한: 4KB 제한으로 인해 대규모 데이터를 저장할 수 없음.
  2. 클라이언트 의존성: 쿠키가 손상되거나 삭제될 가능성.
  3. 보안 취약성: 잘못 설정된 쿠키는 보안 문제를 초래.

8. 요약: 쿠키의 장단점

장점단점
클라이언트 상태 정보를 쉽게 저장하고 관리 가능용량 제한(4KB)
서버 부하 감소 (상태 정보를 서버에 저장하지 않음)클라이언트에서 조작 가능 (보안 문제 발생 가능)
수명 설정 가능 (짧거나 긴 시간 동안 유지 가능)HTTP를 통해 전송되므로 도청 위험 (HTTPS 필요)
브라우저 간 호환성 높음쿠키의 잘못된 설정으로 보안 문제가 발생할 가능성 있음

1.3 쿠키와 세션의 차이점

항목쿠키(Cookie)세션(Session)
저장 위치클라이언트(브라우저)서버
데이터 용량4KB 제한서버 메모리에 의존
보안클라이언트에서 쉽게 조작 가능 (HTTPS로 전송 암호화 필요)클라이언트에서 직접 접근 불가, 서버가 관리
속도빠름 (클라이언트에 저장)상대적으로 느림 (매 요청마다 서버 확인 필요)
유지 시간만료 시간 설정 가능, 브라우저 종료 시 삭제 가능세션 타임아웃 설정 가능
사용 사례사용자의 기본 설정 저장, 로그인 상태 유지사용자 인증, 장바구니 데이터, 민감한 데이터 처리

쿠키를 통한 로그인 과정

flowchart TD
    A["login_form.jsp (아이디와 비밀번호 입력)"]
    B["login_ok.jsp (로그인 검사)"]
    C["login_complete.jsp (로그인 완료 페이지 - 쿠키 검사)"]

    A -->|id & password 입력| B
    B -->|검사 성공| C
    C -->|쿠키 유효| C
    C -->|쿠키 무효| A
    B -->|검사 실패| A
profile
개발자

0개의 댓글