
수업 내용 정리
JSON 형식의 데이터를 저장하는 토큰
API 요청을 인증하는 수단으로 사용
쿠키, 세션의 단점을 보완
JWT를 활용한 로그인 사례
(Token : 데이터 베이스의 호출이 없다, 토큰을 가지고 유효한지 유효하지 않은지 알 수 있다)

JWT의 구성(Token의 구성 모습)
Token 자체에 중요한 정보를 넣으면 안된다
(token log를 통해서 data 내용을 알 수 있기 때문에)
토큰 검증

쿠키 옵션, Set-Cookie 시 다양한 옵션이 있음
쿠키명 = 쿠키값 : 기본적인 쿠키의 값이다. mycookie=test 와 같이 pair로 설정한다
Expires = 날짜 : 만료 기한이다. 이 기한이 지나면 쿠키가 제거된다. 기본값은 클라이언트가 종료될 때까지이다.
Max-age = 초 : Expires와 비슷하지만 날짜 대신 초를 입력할 수 있다. 해당 초가 지나면 쿠키가 제거되며 Expires보다 우선시한다.
Domain = 도메인명 : 쿠키가 전송될 도메인을 특정할 수 있다. 기본값은 현재 도메인이다
Path = URL : 쿠키가 전송될 URL을 특정할 수 있다. 기본값은 '/' 이며 이 경우 모든 URL에서 쿠키를 전송할 수 있다
Secure : HTTPS일 경우에만 쿠키가 전송된다
HttpOnly : 설정시 자바스크립트에서 쿠키에 접근할 수 없다. 쿠키 조작을 방지하기 위해 설정하는 것이 좋다
쿠키의 정보는 노출되고 수정되는 위험이 있음
세션의 동작 방식
단방향 암호화
Hash 사용하기(sha512)
const crypto = require("crypto")
console.log(
"bash64: ",
crypto.createHash("sha512").update("password1234").digest("base64")
const http = require('http');
const fs = require('fs').promises;
const path = require('path');
const parseCookies = (cookie = '') =>
cookie
.split(';')
.map(v => v.split('='))
.reduce((acc, [k, v]) => {
acc[k.trim()] = decodeURIComponent(v);
return acc;
}, {});
http.createServer(async (req, res) => {
const cookies = parseCookies(req.headers.cookie); // { mycookie: 'test' }
// 주소가 /login으로 시작하는 경우
if (req.url.startsWith('/login')) { // 로그인으로 들어왔다
const url = new URL(req.url, 'http://localhost:8084'); // 8084 받아옴
const name = url.searchParams.get('name');
const expires = new Date();
// 쿠키 유효 시간을 현재시간 + 5분으로 설정
expires.setMinutes(expires.getMinutes() + 5); // 해당 쿠키의 유효시간을 5분, expires에 가져왔다
res.writeHead(302, {
Location: '/',
'Set-Cookie': `name=${encodeURIComponent(name)}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`, // Set-Cookie에 내가 넣고 싶은 정보를 모두 넣을 수 있다
});
res.end();
// name이라는 쿠키가 있는 경우
} else if (cookies.name) {
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(`${cookies.name}님 안녕하세요`);
} else {
try {
const data = await fs.readFile(path.join(__dirname, 'cookie2.html'));
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(data);
} catch (err) {
res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(err.message);
}
}
})
.listen(8084, () => {
console.log('8084번 포트에서 서버 대기 중입니다!');
});
const http = require('http');
const fs = require('fs').promises;
const path = require('path');
const parseCookies = (cookie = '') =>
cookie
.split(';')
.map(v => v.split('='))
.reduce((acc, [k, v]) => {
acc[k.trim()] = decodeURIComponent(v);
return acc;
}, {});
const session = {};
http.createServer(async (req, res) => {
const cookies = parseCookies(req.headers.cookie);
if (req.url.startsWith('/login')) {
const url = new URL(req.url, 'http://localhost:8085');
const name = url.searchParams.get('name');
const expires = new Date();
expires.setMinutes(expires.getMinutes() + 5);
const uniqueInt = Date.now(); // 현재 시간
session[uniqueInt] = { // 현재 시간을 key로 가지고 이 key 안에는 name과 expires가 있다
name,
expires,
};
res.writeHead(302, {
Location: '/',
'Set-Cookie': `session=${uniqueInt}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`, // key를 보내서 client가 cookie에 저장할 수 있게 해준다
});
res.end();
// 세션쿠키가 존재하고, 만료 기간이 지나지 않았다면
} else if (cookies.session && session[cookies.session].expires > new Date()) {
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(`${session[cookies.session].name}님 안녕하세요`);
} else {
try {
const data = await fs.readFile(path.join(__dirname, 'cookie2.html'));
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(data);
} catch (err) {
res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(err.message);
}
}
})
.listen(8085, () => {
console.log('8085번 포트에서 서버 대기 중입니다!');
});
npm install jsonwebtoken dotenv
const jwt = require("jsonwebtoken");
const token = jwt.sign({id : "kdkd"}, "shhhh", { // id : kdkd, 비밀키(탈취되면 안됨) : shhhh
expiresIn : "1m" // 1분만 유효
issuer : "yubin",
});
console.log(token);