Coding/Back - Spring Framework

보안 기초 : 쿠키(Cookie) & 세션(Session) #Day23

꿀딴지- 2023. 9. 18. 14:15

HTTPS : 보안인증서가 있는 http

  • 암호화 : 클라이언트와 서버가 데이터를 암호화하여 주고받기 위해 비대칭키 방식과 대칭키 방식 혼용하여 사용
  • 인증서 : rootCA로 부터 서버의 신원을 보증

HTTPS 사설인증서 발급 및 서버 구현

자바에서 지원하는 인증서 형식

  • PKCS12 (public key cryptographic standards #12) :여러 인증서와 키를 포함할 수 있으며, 암호로 보호된 형식(널리 사용)
  • JKS (Java KeyStore) : PKCS12와 유사. 독점 형식이며 Java 환경으로 제한

1. 인증서 생성

mkcert : PKCS12형태의 사설인증서 생성 라이브러리

brew install mkcert

//로컬을 인증된 발급기관으로 추가
mkcert -install
//pkcs12 인증서 생성 (현 위치)
mkcert -pkcs12 localhost

2. web app 서버에 인증서 등록

  • 생성된 인증서를 resources 폴더로 이동
  • application설정에 추가
#application.properties
server.ssl.key-store=classpath:localhost.p12  #  -> 인증서 경로를 적습니다.
server.ssl.key-store-type=PKCS12              #  -> 인증서 형식을 적습니다.
server.ssl.key-store-password=changeit        #  -> 인증서 비밀번호를 적습니다.

# 여기서 비밀번호인 changeit은 비밀번호를 설정하지 않았을 때의 기본값입니다.
# 인증서 비밀번호는 인증서를 생성할 때 설정하거나 생성 후 변경해줄 수 있습니다.
#application.yml
server:
  ssl:
    enabled: true
    key-store: classpath:localhost.p12
    key-store-password: changeit
    key-store-type: PKCS12
  port: 8080

spring boot 실행결과에서, Tomcat started on port(s): 8080 (https) → https로 실행됨을 확인

 

쿠키(Cookie)와 세선(Session)

쿠키 :

서버는 클라이언트에 인증정보를 담은 쿠키를 전송하고, 클라이언트는 전달받은 쿠키를 요청과 같이 전송하여 Stateless 한 인터넷 연결을 Stateful 하게 유지할 수 있다.

기본적으로는 쿠키는 오랜 시간 동안 유지될 수 있고, 자바스크립트를 이용해서 쿠키에 접근할 수 있기 때문에 쿠키에 민감한 정보를 담는 것은 위험

ex. 사용자 선호, 테마 등 장시간 보존해야하는 정보 저장에 적합

  • 서버가 일방적으로 클라이언트에 전달하는 작은 데이터로 서버가 웹 브라우저에 정보를 저장하고 불러올 수 있는 수단
  • 해당 도메인에 대해 쿠키가 존재하면, 웹 브라우저는 서버에게 http 요청 시 쿠키를 함께 전달
  • 삭제하지 않는다면 사라지지 않는 특성
  • 민감정보는 암호화(해싱처리) 되어있음
  • js로 쉽게 접근이 가능함(취약함)
  • 쿠키옵션
    • domain - 서버와 요청의 도메인이 일치하는 경우 쿠키 전송
    • path - 서버 요청의 세부 경로가 일치하는 경우 쿠키 전송
    • maxage/expires - 쿠키의 유효기간 설정
    • httpOnly - 스크립트의 쿠키 접근 가능 여부 설정
    • secure - HTTPS에서만 쿠키 전송 여부 설정
    • sameSite - 같은 사이트에서만 쿠키를 사용할 수 있게 하는 설정 : None, Lax, Strict

참고. Cross-Origin , Cross-Site

  • Cross-Origin : 서버의 도메인, 프로토콜, 포트 중 하나라도 다른 경우 Cross-Origin으로 구분
  • Cross-Site : eTLD+1이 다른 경우 Cross-Site로 구분. 여기서 eTLD+1 이란, .com, .org과 같이 도메인의 가장 마지막 부분을 TLD(Top Level Domain, 최상위 도메인)라고 하는데, 이 최상위 도메인의 바로 왼쪽의 하위 레벨 도메인을 합한 것을 eTLD+1. 참고로, 요즘 자주 볼 수 있는 .io의 경우 바로 왼쪽의 주소를 하나 더 합한 것을 TLD라고 판단함

세션 :

서버가 클라이언트에 유일하고 암호화된 ID를 부여하고 중요데이터는 서버에서 관리

  • (세션 생성) 사용자가 인증에 성공한 상태
    • 서버 : 주로 in-memory, 또는 세션 스토어(redis 등과 같은 트랜잭션이 빠른 DB)에 저장
    • 클라이언트 : 각 세션을 구분할 수 있는 세션 아이디(서버생성)를 보통 클라이언트에 세션 성공을 증명할 수단으로써 세션 아이디를 받음 → 쿠키에 저장
  • (세션 사용) 쿠키를 통해 유효한 세션 아이디가 서버에 전달되고, 세션 스토어에 해당 세션이 존재한다면 서버는 해당 요청 처리
  • (세션 만료)
    • 서버 : 세션 정보를 삭제
    • 클라이언트 : 쿠키(세션 아이디)를 갱신 → 서버가 클라이언트의 쿠키를 임의로 삭제할 수는 없고, set-cookie로 클라이언트에게 쿠키를 전송할 때 세션 아이디의 키값을 무효한 값으로 갱신

(요약) web에서의 인증/인가

세션 : 출입증 + 출입가능리스트 → 양쪽에서 티켓을 반씩 가지고 있음

 

세션(서버 - 메모리 있기 때문에)이 많을 수록 메모리 관리가 힘듦

  • 세션으로 메모리가 차는 것은 좋은 방식은 아님 (그치만 필수적인 존재)
    1. 메모리에 관리 2) DB에 관리(구성이 어렵고 관리 point가 생김) 3) redis (세션 저장소, key와 쌍으로 관리할 수 있음)

↔ 쿠키(클라이언트) : 서버에서 처리할 게 없음(클라이언트 정보)

  • 쿠키 발급 : 서버에서 클라이언트한테 발급함
  • 쿠키 사용 : 클라이언트가 서버에게 쿠키값을 가지고 요청해 올 수 있음

 

로그인

  1. 세션방식 : springSecurity의 default 방식
  2. 쿠키방식 - 토큰(jwt 토큰)
  • 세션을 사용하지 않고 쿠키방식으로도 가능(토큰)
  • 서버가 생성한 토큰을 쿠키에 실어서 주면, 로그인 시 토큰을 들고 요청이 오면 서버에서 복호화하여 인증함
  • jwt : 토큰방식 중 하나 (거의 표준)