보안과 환경변수
PUT 과 PATCH 의 차이
쿠키 vs 세션 vs JWT
Sateful vs Satrefuless
JWT 코드
왜 쿠키가 아니라 JWT인가?
참조한 페이지
위와같은 코드를 git hub에 올렸다고 생각해보자.(참고로 실제 접속키는 저게 아니니 걱정 마시길)
mongoDB의 id와 password가 모두 나와 있다. 그렇기 때문에 개인 프로젝트라면 개인이 만들어 둔 DB의 문제이다. 하지만, 회사 단위의 접속키였다면, 매우 심각한 보안 사고로 취급되어 개인에게도 나쁜일이 일어날 것이며, 최악의 경우에는 회사의 자산이 모두 유출 된 이후에 발견해서 회사가 망할 수 도 있을 것이다.
아이디, 비밀번호는 물론 클러스터 정보같은 것도 지우고, 환경변수를 이용해서 접속을하자. 업로드 시 보안문제도 해결되지만, 테스트 환경과 같은 코드를 구릴 때 테스트용 클러스터로 바꾸기도 간편하다.
const express = require("express");
const cookieParser = require("cookie-parser")
// npm i cookie-parser
const app = express();
app.use(cookieParser())
// 클라이언트에 쿠키를 전달한다.
app.get("/set-cookie", (req, res) => {
let expires = new Date();
expires.setMinutes(expires.getMinutes() + 60); // 만료 시간을 60분으로 설정합니다.
// 쿠키의 이름 내용물(값)
res.cookie('name', 'sparta', {
expires: expires
});
return res.status(200).end();
});
app.get("/get-cookie", (req, res) => {
// 클라이언트가 전달한. 쿠키정보
// const cookie = req.headers.cookie;
// 문자열로 출력
// 쿠키가 많아지면 불편하기 때문에 cookie-parser 라는 미들웨어를 사용한다.
//쿠키들을 전부 객체로 만들어준다.
const cookies = req.cookies;
// 객체로 출력
console.log(cookies); // 출력한다. name=sparta
return res.status(200).json({ cookies });
})
// 사용자의 정보를 저장할 세션(= 자물쇠)
let sesseion = {}; // Key - Value()
app.get('/set-session', (req,res) =>{
const name = "sparta"; // 세션에 저장할 데이터
// 현재 시간을 바탕으로 고유값을 만든다.
const uniqueInt = Date.now(); // 클라이언트에 할당할 key 값
sesseion[uniqueInt] = name; // 세션에 뎇이터를 저장
res.cookie("sessionKey", uniqueInt); // 클라이언트에 쿠키를 할당한다.
res.status(200).end();
});
// 쿠키로 세션의 값을 가져오자.
app.get('/get-session', (req,res) => {
// 객체 분해 구조 할당
const {sessionKey} = req.cookies;
const seesionItem = sesseion[sessionKey];
console.log(seesionItem);
return res.status(200).json({seesionItem: seesionItem});
});
app.listen(5002, () => {
console.log(5002, "번 포트로 실행되었습니다.")
})
세션
그래서 사용자에게는 정보가 아니라 키를 주는 방식의 세션을 사용한다.
JWT
npm i jsonwebtoken
이름과 다르게 node.js가 아니어도 된다.
JSON 형태의 데이터를 안전하게 교환하게 해주는 표준 규격. header.payload.signature
의 3가지 데이터를 포함한다. = 항상 .
이 두 개 포함된다.
JWT는 비밀 키를 몰라도 복호화(Decode, 해독)이 가능하다. 즉, 변조가 어려운 것이지, 데이터의 비밀을 보장하는 것이 아니다. 그러므로 중요한 정보를 넣지 말자.
쿠키/세션은 데이터를 교환하고 관리하는 방식이지만, JWT는 단순히 데이터를 표현하는 방식일 뿐이다.
JWT로 만든 데이터를 브라우저로 보내도, 쿠키처럼 자동으로 저장되지는 않지만, 변조가 거의 불가능하고, 서버에 데이터를 저장하기 때문에, 서버를 sateless로 관리할 수 있다.
JsonWebToken
// npm i jsonwebtoken
// jsonwebtoken 호출
const jwt = require("jsonwebtoken");
// payload 생성
const payloadData = {
myPayloadData : 1234
}
// 패키지 호훌 ↓ | 넣을 데이터 ↓ | ↓ 사용할 기밀 키
const token = jwt.sign(payloadData, "mysecretKey")
console.log(token)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJteVBheWxvYWREYXRhIjoxMjM0LCJpYXQiOjE2ODc0ODg2MTR9.ILH3QeTHoqGGyF6skQuczub03PxSV9AHuszvxzbQRG4
같은 값이 출력 될 것이다.
https://jwt.io/
에 접속해서 해독해 보자.
payload 값은 정상으로 나오는데, 값이 변조 된것으로 나온다. 해독키가 다르기 때문이다.
우리가 설정한 기밀키인 [mysecretKey]를 넣으면 정상으로 나온다.
앞서 말한대로 기밀키를 몰라도 누구든지 내용을 볼 수 있다.
// npm i jsonwebtoken
// jsonwebtoken 호출
const jwt = require("jsonwebtoken");
// payload 생성
const payloadData = {
myPayloadData : 1234
}
// 패키지 호출 ↓ | 넣을 데이터 ↓ | ↓ 사용할 기밀 키
const token = jwt.sign(payloadData, "mysecretKey")
console.log(token)
// 복호화하기
const decodedValue = jwt.decode(token);
console.log("복호화한 token 입니다.", decodedValue)
// 기밀키 검증
const decodedValueByVerify = jwt.verify(token,"mysecretKey");
console.log ("검증 결과 괜찮으면 출력 :", decodedValueByVerify);
// 기밀키 검증 실패
const decodedValueByVerifyToFail = jwt.verify(token,"asdrfwaetwesgdfc");
console.log ("검증 결과 괜찮으면 출력 :", decodedValueByVerifyToFail);
비밀키가 일치하지 않으면 검즘에 실패하고 JsonWebTokenError
를 뱉는다.
const express = require('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, "번호로 서버가 켜졌어요!");
});
쿠키는 브라우저에서도 수정이 가능하다. 메일만 master로 바꾸면, 마스터 계정의 권한이 탈취되는 사고가 일어나버린다.
const express = require('express');
const JWT = require("jsonwebtoken");
const app = express();
app.post('/login', async (req, res) => {
// 사용자 정보
const user = {
userId: 203,
email: "archepro84@gmail.com",
name: "이용우",
}
// 사용자 정보를 JWT로 생성
const userJWT = await 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, "번호로 서버가 켜졌어요!");
});
같은 내용물이지만 JWT에 할당한다. = 서버에서 만든 값인지 아닌지 인증 할 수 있다.