본 내용은 내일배움캠프에서 활동한 내용을 기록한 글입니다.
브라우저가 서버로부터 응답으로 Set-Cookie 헤더를 받은 경우 해당 데이터를 저장한 뒤 모든 요청에 포함하여 보냄
쿠키는 사용자가 naver.com
과 같은 웹 사이트를 방문할 때마다 이전에 방문했던 정보를 기억하는 데이터 파일
데이터를 여러 사이트에 공유할 수 있기 때문에 보안에 취약할 수 있음
쿠키를 기반으로 구성된 기술
클라이언트가 마음대로 데이터를 확인 할 수 있던 쿠키와는 다르게 세션은 데이터를 서버에만 저장
일반적으로 세션 Id를 쿠키를 이용해 클라이언트에게 전달하여, 서버는 이 세션 Id를 사용해 저장된 세션 데이터를 조회
보안성은 좋으나, 반대로 사용자가 많은 경우 서버에 저장해야 할 데이터가 많아져서 서버 컴퓨터가 감당하지 못하는 문제가 생기기 쉬움
Set-Cookie
를 이용하여 쿠키 할당하기// 'Set-Cookie'를 이용하여 쿠키를 할당하는 API
app.get("/set-cookie", (req, res) => {
let expire = new Date();
expire.setMinutes(expire.getMinutes() + 60); // 만료 시간을 60분으로 설정
res.writeHead(200, {
'Set-Cookie': `name=sparta; Expires=${expire.toGMTString()}; HttpOnly; Path=/`,
});
return res.end();
});
res.cookie()
를 이용하여 쿠키 할당하기// 'res.cookie()'를 이용하여 쿠키를 할당하는 API
app.get("/set-cookie", (req, res) => {
let expires = new Date();
expires.setMinutes(expires.getMinutes() + 60); // 만료 시간을 60분으로 설정
res.cookie('name', 'sparta', {
expires: expires
});
return res.end();
});
// 'req.headers.cookie'를 이용하여 클라이언트의 모든 쿠키를 조회하는 API
app.get('/get-cookie', (req, res) => {
const cookie = req.headers.cookie;
console.log(cookie); // name=sparta
return res.status(200).json({ cookie });
});
# yarn을 이용해 cookie-parser를 설치합니다.
yarn add cookie-parser
app.use(cookieParser());
import cookieParser from 'cookie-parser';
app.use(cookieParser());
// 'req.cookies'를 이용하여 클라이언트의 모든 쿠키를 조회하는 API
app.get('/get-cookie', (req, res) => {
const cookie = req.cookies;
console.log(cookie);
return res.status(200).json({ cookie });
});
쿠키의 경우 서버를 재시작하거나 새로고침을 하더라도 로그인이 유지됨
사용자에게는 편리하지만, 서버의 입장에서는 보안 문제가 발생할 수 있음
그렇기에 쿠키에는 사용자가 누구인지 확실하게 구분할 수 있는 정보를 넣어주어야 할
민감한 정보는 서버에서만 관리하고, 사용자 식별 정보를 통해 사용자의 정보를 반환
/set-session
API 만들기
let session = {};
app.get('/set-session', function (req, res, next) {
// 현재는 sparta라는 이름으로 저장하지만, 나중에는 복잡한 사용자의 정보로 변경될 수 있음
// ID, IP, user-agent 등등
const name = 'sparta';
const uniqueInt = Date.now();
// 세션에 사용자의 시간 정보 저장
// 시간 정보를 세션 ID로 사용
session[uniqueInt] = { name };
res.cookie('sessionKey', uniqueInt);
return res.status(200).end();
});
/set-session
API 만들기app.get('/get-session', function (req, res, next) {
const { sessionKey } = req.cookies;
// 클라이언트의 쿠키에 저장된 세션 키(ID)로 서버의 세션 정보를 조회
const name = session[sessionKey];
return res.status(200).json({ name });
});
JWT(Json Web Token)은 웹 표준으로써, 서버와 클라이언트 사이에서 정보를 안전하게 전송하기 위해 도움을 주는 웹 토큰(Web Token)
다양한 암호화 알고리즘을 사용할 수 있어, 신뢰성을 보장함
헤더, 페이로드, 시그니처로 구성됨
JWT는 비밀 키를 모르더라도 복호화(Decode)가 가능
변조만 불가능 할 뿐, 누구나 복호화하여 보는것은 가능하다는 의미
민감한 정보(개인정보, 비밀번호 등)는 담지 않도록 해야함
데이터를 교환하고 관리하는 방식인 쿠키/세션과 달리, JWT는 단순히 데이터를 표현하는 형식
JWT로 만든 데이터는 변조가 어렵고, 서버에 별도의 상태 정보를 저장하지 않기 때문에, 서버를 Stateless(무상태)로 관리할 수 있음
쿠키와 세션은 사용자의 로그인 정보나 세션 데이터를 서버에 저장하므로 상태를 유지하기 때문에 Stateful(상태 보존)하게 데이터가 관리됨
Node.js 서버가 언제든 죽었다 살아나도 똑같은 동작을 하면 Stateless
서버가 죽었다 살아났을때 조금이라도 동작이 다른 경우 Stateful
jsonwebtoken
라이브러리의 sign
메서드를 사용해 JWT를 생성import jwt from 'jsonwebtoken';
const token = jwt.sign({ myPayloadData: 1234 }, 'mysecretkey');
console.log(token); // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJteVBheWxvYWREYXRhIjoxMjM0LCJpYXQiOjE2OTA4NzM4ODV9.YUmYY9aef9HOO8f2d6Umh2gtWRXJjDkzjm5FPhsQEA0
jsonwebtoken
라이브러리의 decode
메서드를 사용해 JWT를 복호화import jwt from 'jsonwebtoken';
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJteVBheWxvYWREYXRhIjoxMjM0LCJpYXQiOjE2OTA4NzM4ODV9.YUmYY9aef9HOO8f2d6Umh2gtWRXJjDkzjm5FPhsQEA0";
const decodedValue = jwt.decode(token);
console.log(decodedValue); // { myPayloadData: 1234, iat: 1690873885 }
jsonwebtoken
라이브러리의 verify
메서드를 사용해 JWT를 검증import jwt from 'jsonwebtoken';
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJteVBheWxvYWREYXRhIjoxMjM0LCJpYXQiOjE2OTA4NzM4ODV9.YUmYY9aef9HOO8f2d6Umh2gtWRXJjDkzjm5FPhsQEA0";
const decodedValueByVerify = jwt.verify(token, "mysecretkey");
console.log(decodedValueByVerify);
// 검증에 성공할 경우 => { myPayloadData: 1234, iat: 1690873885 }
// 검증에 실패할 경우 => JsonWebTokenError: invalid signature
JWT가 인증 서버에서 발급되었는지 위변조 여부를 확인할 수 있음
누구든지 JWT 내부에 들어있는 정보를 확인할 수 있음 (복호화)
사용자의 정보가 sparta
이름을 가진 쿠키에 할당
쿠키의 속성값이나 만료 시간을 클라이언트가 언제든지 수정할 수 있음
쿠키의 위변조 여부를 확인 할 수 없음
import express from 'express';
const app = express();
app.post('/login', function (req, res, next) {
const user = { // 사용자 정보
userId: 203, // 사용자의 고유 아이디 (Primary key)
email: "archepro84@gmail.com", // 사용자의 이메일
name: "이용우", // 사용자의 이름
}
res.cookie('sparta', user); // sparta 라는 이름을 가진 쿠키에 user 객체를 할당
return res.status(200).end();
});
app.listen(5002, () => {
console.log(5002, "번호로 서버가 켜졌어요!");
});
사용자의 정보를 Payload에 저장한 JWT를 sparta
이름을 가진 쿠키에 할당
JWT를 생성할 때 위변조 여부를 확인할 수 있는 비밀키를 사용
쿠키의 만료시간과 별개로 JWT의 만료시간을 설정
import express from 'express';
import JWT from 'jsonwebtoken';
const app = express();
app.post('/login', (req, res) => {
// 사용자 정보
const user = {
userId: 203,
email: 'archepro84@gmail.com',
name: '이용우',
};
// 사용자 정보를 JWT로 생성
const userJWT = JWT.sign(
user, // user 변수의 데이터를 payload에 할당
'secretOrPrivateKey', // JWT의 비밀키를 secretOrPrivateKey라는 문자열로 할당
{ expiresIn: '1h' }, // JWT의 인증 만료시간을 1시간으로 설정
);
// userJWT 변수를 sparta 라는 이름을 가진 쿠키에 Bearer 토큰 형식으로 할당
res.cookie('sparta', `Bearer ${userJWT}`);
return res.status(200).end();
});
app.listen(5002, () => {
console.log(5002, '번호로 서버가 켜졌어요!');
});
2주차 남은 강의를 시청
최대한 시청 후 과제 문서를 작성할 수 있도록 노력할 것!!
내일도 시간이 많지 않기 때문에 오전, 오후에 최대한 시청할 예정
예비군으로 밀린 강의를 시청함
원래는 2주차를 오늘 안에 다 시청하려고 했으나, 생각보다 내용이 어려웠음
완전히 막힌다기 보다는 내용이 어려워서 검색하면서 이해하느라 진행이 느렸음
현재 2주차 1/3 정도 완료한 상태
주말을 이용해서 최대한 강의를 들을 예정