오늘 배운 쿠키나 세션은 인증과 보안에 대한 내용이었다.
개념에 대해 정리도 좀 하고, 오늘 실습이 꽤 길고 내용이 많았어서 그 내용에 대해서도 정리를 해야겠다.
어제 배운 바에 의하면 HTTP는 무상태성을 가지고 있기 때문에 서버가 클라이언트의 상태를 보존하지 않는다. 실무에서 모든 걸 무상태로 설계할 수 없는 경우들이 있는데, 예를 들어서 오늘 실습으로 구현한 로그인 기능이 그렇다. 이런 경우에 사용할 수 있는 방법들이 브라우저 쿠키, 서버 세션, 그리고 토큰이다.
그래서
서버가 클라이언트에 영속성(지속성) 있는 데이터를 저장하거나, 서버가 클라이언트에 저장된 데이터를 쿠키를 이용해 다시 가져오는 것을 말한다.
영속성 있는 데이터는 예를 들자면 로그인 상태/인증 정보 유지, 장바구니 정보 유지, 나이트 모드 같은 어플리케이션의 테마 등이 있다.
서버가 클라이언트에 쿠키를 이용해 데이터를 저장하고, 다시 쿠키를 이용해 저장된 데이터를 가지고 올 때, 특정 조건들을 만족시켜야 하는데, 그 조건들을 설정하는 것을 '쿠키 옵션'이라고 한다.
sameSite = ‘Lax’ : GET 매서드 요청만 쿠키 전송 가능
sameSite = ‘Strict’ : 쿠키 전송 불가 (same-site에서만 쿠키 보낼 수 있다는 것)
sameSite = ‘none’ : 모든 메서드 요청에 대해 쿠키 전송 가능 (이 옵션은 Secure 쿠키 옵션이 필요함)
브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리. (fetch API 보다 사용이 간편하면서 추가적 기능들이 포함)
npm install axios
axios.get("url"[,config])
//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 버전으로 만들 수도 있음.
쿠키는 정보를 클라이언트에 보관했다면 세션은 중요 데이터를 서버에서 관리하는 방식이다. (서버가 클라이언트에 유일하고 암호화된 ID를 부여함.)
사실 세션이라는 말 자체는 '사용자가 인증에 성공한 상태'를 말한다.
세션이 만들어지면 각 세션을 구분할 수 있는 세션 아이디가 만들어지는데, 이 세션 아이디는 클라이언트에 세션 성공을 증명할 수단으로 전달하게 됨.
세션의 단점은 많은 사용자들의 정보가 있는 경우에 서버 저장 공간 부족의 문제가 있고,
여전히 쿠키를 함께 사용하고 있기 때문에 XSS 공격으로 인해 세션 쿠키가 탈취되면 보안 문제가 생긴다.
세션을 위한 미들웨어로 서버에서 세션을 위한 공간을 쉽게 다룰 수 있도록 만들어 줌.
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 구현은 거의 동일했고, 각각 표현방식이 조금 다를 뿐 유사하게 구현되었다.
//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');
모든 코드를 복붙하는 건 의미가 없을 것 같다.
그냥 혼자 다시 풀어보는 게 좋을 거 같아 로그인 기능이 작동하는 흐름만 정리하고 오늘의 블로그 작성은 끝내겠다.