Network - cookie & session

수현·2023년 10월 1일
0

CS

목록 보기
5/11

쿠키는 브라우저 로컬에 저장되는 key-value 형태의 작은 데이터 파일로 클라이언트의 상태 정보를 로컬에 저장하여 참조할 수 있다. 사용자 인증이 유효한 시간을 명시할 수 있으며 유효한 시간 내에서는 브라우저가 종료되어도 인증이 유지된다.

쿠키의 전달

서버와 클라이언트는 쿠키를 주고 받을 때 HTTP header에 포함하여 전달한다. 로그인으로 예시를 들어보겠다.

사용자가 로그인에 성공하면 서버는 Set-Cookie를 사용하여 user 정보를 cookie에 담아 클라이언트에 전달한다.

→ 이를 받으면 웹 브라우저의 내부에 있는 쿠키 저장소에 받은 정보를 저장한다.

→ 이후 브라우저는 서버에 요청을 보낼 때마다 쿠키 저장소에 있는 정보를 자동으로 Cookie에 담아서 함께 보낸다.

쿠키의 구성

서버에서 쿠키를 세팅할 때!

ex) Set-Cookie: sessionId=abcde12345; expires=Sat, 26-Dec-2020 00:00:00 GMT; path=/; domain=example.com; Secure

  • 쿠키 생명 주기

    • expires : 만료일은 GMT 기준으로 작성하며, 만료일이 되면 쿠키는 자동으로 삭제된다.

    • max-age : 0이나 음수를 지정하면 쿠키가 삭제되며 expires와 같이 만료일이 지나면 쿠키가 삭제된다.

    • 만료일자를 생략하면 브라우저 종료 시까지만 유지(세션 쿠키), 만료일자를 입력하면 해당 날짜까지 유지(영속 쿠키)

  • Domain

    • domain 명시 : 명시한 문서 기준 도메인 + 서브 도메인을 모두 포함(dev.example.com도 쿠키 접근)

    • domain 생략 : 현재 문서 기준 도메인만 적용(dev.example.com은 쿠키 미접근)

  • Path : 지정한경로를 포함한 하위 경로 페이지만 쿠키 접근, 일반적으로 루트로 지정함('/')

  • 보안

    • Secure : 쿠키는 http, https 모두 전송하지만 Secure를 적용하면 https인 경우에만 전송

    • HttpsOnly : XSS 공격 방지, JS에서 접근 불가(document.cookie)하여 HTTP전송에만 사용된다.

    • SameSite : XSRF 공격 방지, 요청 도메인과 쿠키에 설정된 도메인이 같은 경우에만 쿠키 전송

쿠키의 특징

  • 사용자 로그인 세션 관리, 광고 정보 트래킹 등에 사용될 수 있다.

  • 쿠키 정보는 항상 서버에 전송되므로 네트워크 트래픽이 추가되어 최소한의 정보만 사용한다.

  • 데이터를 브라우저에 가지고 있다가 서버에 필요할 때만 전송하고 싶다면 웹 스토리지(localStorage, sessionStorage) 사용

  • 보안에 민감한 주민번호나 신용카드 정보 등은 저장하지 않는다!!


Session

세션은 쿠키를 기반으로 하지만 사용자 정보 파일을 서버측에서 저장하고 관리한다. 서버에서 클라이언트에게 세션 ID를 생성하여 부여하고 해당 사용자 정보를 포함한 세션 정보를 서버의 메모리, DB 등에 저장한다.

클라이언트는 서버에게 받은 세션ID를 쿠키에 저장하고, 이를 이용하여 서버는 요청을 받을 때 사용자를 식별하고 세션의 정보를 사용할 수 있다.

세션의 특징

  • 사용자에 대한 정보를 서버에 두기 때문에 쿠키보다 보안에 좋지만, 사용자가 많을수록 서버 메모리/DB공간을 많이 차지하게 된다. → 동시 접속자가 많을 경우 서버에 부하를 주게 되어 성능이 저하될 수 있다.

  • 로그인과 같이 보안 상 중요한 작업을 수행할 때 사용한다.

세션 로그인

라이브러리를 사용할 수도 있지만 직접 구현하면서 동작 과정을 파악해보자.

class SessionStorage {
	storage: Record<string, sessionData>;
	private sessionTimeOut: number;

	constructor() {
		this.storage = {};
		this.sessionTimeOut = SESSION_TIMEOUT;
	}

	save(sid: string, userId: string, nickname: string) {
		const sessionData: sessionData = {
			userId: userId,
			nickname: nickname,
			expirationTime: Date.now() + this.sessionTimeOut,
		};
		this.storage[sid] = sessionData;
		return sessionData.expirationTime;
	}
}
  • 세션을 메모리에 저장하여 관리하기 위해 session storage를 만들었다.
  • 세션 아이디를 key로, user 정보를 value로 하여 세션 스토리지에 저장하도록 했다.
  • 만료일을 지정하여 나중에 만료일이 지났을 경우 로그인 상태를 유지하지 못하도록 했다.
const generateSessionId = (): string => {
	const characters = CHARACTERS;
	let sessionId = '';
	for (let i = 0; i < 32; i++) {
		sessionId += characters[Math.floor(Math.random() * characters.length)];
	}
	return sessionId;
};
  • 32자리의 랜덤한 세션 아이디를 만드는 함수이다.
  • character는 영어 대소문자와 숫자를 포함하도록 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'를 사용해주었다.
const sid = generateSessionId();
const expires = sessionStorage.save(sid, userInfo.id, userInfo.nickname);
// cookie에서 사용하는 날짜 형식을 맞추기 위해 Date 객체로 만들고 toUTCString()으로 변환!!
const expireationData = new Date(expires);

headers = {
    Location: `${process.env.DOMAIN}/`,
    'Set-Cookie': `sid=${sid}; expires=${expireationData.toUTCString()}; Path=/`,
};
return new HttpResponse(302, headers);

이제 위의 재료들을 가지고 실제 세션 로그인을 할 수 있다!

세션 아이디 생성 → 세션 스토리지에 저장 → 쿠키 세팅하여 HTTP header로 보내기


참고 자료

https://interconnection.tistory.com/74

profile
실패와 성장을 기록합니다 🎞️

0개의 댓글