[TIL] Cookie, Session, 실습

Jade·2022년 11월 10일
1

Today I learn

목록 보기
50/77
post-thumbnail

오늘 배운 쿠키나 세션은 인증과 보안에 대한 내용이었다.
개념에 대해 정리도 좀 하고, 오늘 실습이 꽤 길고 내용이 많았어서 그 내용에 대해서도 정리를 해야겠다.

어제 배운 바에 의하면 HTTP는 무상태성을 가지고 있기 때문에 서버가 클라이언트의 상태를 보존하지 않는다. 실무에서 모든 걸 무상태로 설계할 수 없는 경우들이 있는데, 예를 들어서 오늘 실습으로 구현한 로그인 기능이 그렇다. 이런 경우에 사용할 수 있는 방법들이 브라우저 쿠키, 서버 세션, 그리고 토큰이다.

그래서

🍪 쿠키란 무엇인가 하면 !

서버가 클라이언트에 영속성(지속성) 있는 데이터를 저장하거나, 서버가 클라이언트에 저장된 데이터를 쿠키를 이용해 다시 가져오는 것을 말한다.

영속성 있는 데이터는 예를 들자면 로그인 상태/인증 정보 유지, 장바구니 정보 유지, 나이트 모드 같은 어플리케이션의 테마 등이 있다.

서버가 클라이언트에 쿠키를 이용해 데이터를 저장하고, 다시 쿠키를 이용해 저장된 데이터를 가지고 올 때, 특정 조건들을 만족시켜야 하는데, 그 조건들을 설정하는 것을 '쿠키 옵션'이라고 한다.

🍪 주로 사용하는 쿠키 옵션들

  • Domain
    : 쿠키 옵션에서 도메인은 서브 도메인(ex: www 등 도메인 앞 추가로 작성되는 부분)이나 세부경로는 포함 x
    서버와 요청의 도메인이 일치하는 경우 쿠키 전송
  • Path
    : 세부 경로로 서버가 라우팅할 때 사용하는 경로 의미. (디폴트는 /)
    서버와 요청의 세부 경로가 일치하는 경우 쿠키 전송
  • MaxAge, Expires
    : 쿠키의 유효기간 설정
    MaxAge는 초 단위 설정, Expires는 클라이언트 시간 기준으로 초 설정 MaxAge, Expires 옵션이 없는 경우 '세션쿠키'
    (브라우저가 실행 중일 때 사용할 수 있는 임시 쿠키. 브라우저 종료 시 삭제됨.)
    위 옵션이 존재하는 경우 '영속성 쿠키'
    (브라우저 종료와 상관없이 위 옵션에 지정된 유효시간 만큼 사용 가능)
  • HttpOnly
    : 자바스크립트에서 브라우저의 쿠키에 접근할 수 있는지 여부를 결정하는 옵션
    (클라이언트에서 DOM을 이용해 쿠키에 접근하는 것 막아줌)
    쿠키는 원래 script 태그로 접근이 가능해서 XSS 공격에 취약함.
    이 옵션이 true로 설정되면 script 태그로는 접근 불가능. (디폴트 false)
  • Secure
    : 사용하는 프로토콜에 따른 쿠키 전송 여부 결정하는 옵션
    true인 경우 HTTPS 프로토콜에서만 쿠키 전송 가능
    이 옵션이 없다면 프로토콜에(http or https) 상관없이 모두 쿠키 전송 가능
  • SameSite
    : Cross-Origin 요청 받은 경우 요청에서 사용한 메소드와 해당 옵션의 조합을 기준으로 서버 쿠키 전송 여부 결정.
    지정할 수 있는 옵션 값들은 아래와 같다

sameSite = ‘Lax’ : GET 매서드 요청만 쿠키 전송 가능

sameSite = ‘Strict’ : 쿠키 전송 불가 (same-site에서만 쿠키 보낼 수 있다는 것)

sameSite = ‘none’ : 모든 메서드 요청에 대해 쿠키 전송 가능 (이 옵션은 Secure 쿠키 옵션이 필요함)

여기서 sameSite라는 건 origin의 서버, 도메인, 프로토콜, 포트가 같은 경우를 말함 (하나라도 다르면 Cross-Origin)




Axios

브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리. (fetch API 보다 사용이 간편하면서 추가적 기능들이 포함)

Axios 공식문서 가보자고?

  • 써드 파트 라이브러리라 설치 필요
npm install axios
  • GET 요청을 할 때
axios.get("url"[,config])
  • fetch API와 axios 비교

//fetch API로 만들어보기


//json()은 응답 본문 텍스트를 JSON으로 파싱한 결과로 이행하는 또 다른 프로미스를 반환함.([MDN Fetch](https://developer.mozilla.org/ko/docs/Web/API/Fetch_API/Using_Fetch)

fetch('url 적는 곳! 꼭 문자열로 적어주기!', { method : '매서드 적는 곳!'}
      .then((response) => response.json());
      .then((json) => console.log(json));
	  .catch((error) => console.log(error));



//axios로 만들어보기 

import axios from 'axios';

//axios는 자동으로 json 데이터 형식으로 변환하므로 json() 매서드 필요 없음 
axios
	.get('데이터 받아올 url 적는 곳!')
	.then((response) => {
  		const { data } = response;
  		console.log(data);
})
	.catch((error) => console.log(error));


과제를 하면서 확실히 fetch 보다는 axios가 좀 더 편리하다는 걸 알 수 있었다.
둘 다 프로미스 말고 async awit 버전으로 만들 수도 있음.





Session 🕊

쿠키는 정보를 클라이언트에 보관했다면 세션은 중요 데이터를 서버에서 관리하는 방식이다. (서버가 클라이언트에 유일하고 암호화된 ID를 부여함.)

사실 세션이라는 말 자체는 '사용자가 인증에 성공한 상태'를 말한다.

세션이 만들어지면 각 세션을 구분할 수 있는 세션 아이디가 만들어지는데, 이 세션 아이디는 클라이언트에 세션 성공을 증명할 수단으로 전달하게 됨.

세션의 단점은 많은 사용자들의 정보가 있는 경우에 서버 저장 공간 부족의 문제가 있고,
여전히 쿠키를 함께 사용하고 있기 때문에 XSS 공격으로 인해 세션 쿠키가 탈취되면 보안 문제가 생긴다.

🕊 expression-session

세션을 위한 미들웨어로 서버에서 세션을 위한 공간을 쉽게 다룰 수 있도록 만들어 줌.

const express = require('express');
const session = require('express-session');

const app = express();

app.use(
  session({
    secret: '@codestates',
    resave: false,
    saveUninitialized: true,
    cookie: {
      domain: 'localhost',
      path: '/',
      maxAge: 24 * 6 * 60 * 10000,
      sameSite: 'none',
      httpOnly: false,
      secure: true,
    },
  })
);

위와 같이 세션의 옵션들을 지정할 수 있는데,

쿠키옵션과 비슷해 보이지만 세션은 secret 옵션의 비밀키를 이용해 암호화해 세션 id를 생성하고, 이를 클라이언트에게 쿠키로 전달함.

쿠키로 전송된 세션id는 이에 종속되는 고유한 세션 객체를 가지며, 이는 서버에 저장된다. (세션 객체는 유저별로 독립적으로 생성된 객체이므로 유저별로 각각 다른 데이터를 저장할 수 있음.)

따라서 클라이언트에 유저의 개인정보를 담지 않고도 서버가 클라이언트의 세션 id를 이용해 유저의 인증여부를 판단할 수 있음.

세션 객체 접근하는 매서드 res.session을 통해 세션에 임의 데이터 저장하거나 불러올 수 있음.





실습 : 로그인 기능 구현

실습 과제는 axios, cookie를 이용해 로그인 기능을 구현하고,
두번째 과제에서 axios, session을 이용해 로그인 기능을 구현했다.

cookie와 session 구현은 거의 동일했고, 각각 표현방식이 조금 다를 뿐 유사하게 구현되었다.

  • 서버 로그인 파일을 작성할 때 분기 조건을 잘 지정하기
    : 로그인 아이디창에 입력한 id가 데이터베이스에 있는 유저정보에서 찾아지지 않을 때,
    로그인이 되었을 때, 그런데 로그인이 되었을 때도 두 가지 상황이 있다.
    그냥 로그인을 한 경우와, 로그인 유지란을 체크하고 난 뒤에 로그인 한 경우.
  • res.cookie 메서드는 전달인자로 쿠키 이름, 쿠키 값, 쿠키 옵션을 받는다.
    : 과제에서는 cookiesOptions라는 옵션들이 든 객체를 할당한 변수를 만들어주었다.
//ex 
res.cookie("cookieId", userInfo.id, cookiesOptions);
  • 로그아웃으로 쿠키/세션 삭제할 때
    
	//clearCookie
	res.status(205).clearCookie("cookieId",cookiesOption).send("logout");

	//세션 없애주는 매서드 req.session.destroy
	req.session.destroy();
	res.status(205).send('Logged Out Successfully');


모든 코드를 복붙하는 건 의미가 없을 것 같다.
그냥 혼자 다시 풀어보는 게 좋을 거 같아 로그인 기능이 작동하는 흐름만 정리하고 오늘의 블로그 작성은 끝내겠다.

로그인 기능이 작동하는 흐름

  1. 로그인 버튼 클릭, 서버로 로그인을 요청 (아이디, 비밀번호, 체크여부 전달)
  2. 서버에서 요청을 처리 후 응답 (유저 정보, 쿠키 전달)
  3. 클라이언트에서 응답을 받아 React 상태를 업데이트 함
  4. 조건부 렌더링으로 My Page 표시
    : 로그인할 때 로그인 유지 옵션 선택시 새로고침 or 페이지 재접속 시 다시 로그인 할 필요 없이 서버에서 받아온 쿠키 사용해 회원 정보 받아오도록 함.
  5. 로그아웃 버튼 클릭, 서버로 로그아웃 요청
  6. 서버에서 로그아웃 처리 : 쿠키 삭제
  7. 클라이언트 React 상태 비우기
  8. 조건부 렌더링으로 Login 표시
profile
키보드로 그려내는 일

0개의 댓글