보안, 환경변수, 쿠키,세션,JWT

김민준·2023년 6월 23일
0
보안과 환경변수
PUT 과 PATCH 의 차이
쿠키 vs 세션 vs JWT
Sateful vs Satrefuless
JWT 코드
왜 쿠키가 아니라 JWT인가?

참조한 페이지

보안과 환경변수

위와같은 코드를 git hub에 올렸다고 생각해보자.(참고로 실제 접속키는 저게 아니니 걱정 마시길)

mongoDB의 id와 password가 모두 나와 있다. 그렇기 때문에 개인 프로젝트라면 개인이 만들어 둔 DB의 문제이다. 하지만, 회사 단위의 접속키였다면, 매우 심각한 보안 사고로 취급되어 개인에게도 나쁜일이 일어날 것이며, 최악의 경우에는 회사의 자산이 모두 유출 된 이후에 발견해서 회사가 망할 수 도 있을 것이다.

아이디, 비밀번호는 물론 클러스터 정보같은 것도 지우고, 환경변수를 이용해서 접속을하자. 업로드 시 보안문제도 해결되지만, 테스트 환경과 같은 코드를 구릴 때 테스트용 클러스터로 바꾸기도 간편하다.

PUT 과 PATCH 의 차이.

  • PUT
    모든 자원의 수정, 전달 되지 않은 필드는 null 이나 초기값으로 설정된다.
  • PATCH
    자원의 일부 필드만 수정

쿠키 vs 세션 vs JWT

  • 쿠키
    정보를 클라이언트가 저장하기 때문에 보안에 취약하다.
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가지 데이터를 포함한다. = 항상 .이 두 개 포함된다.

  1. header
    암호화 알고리즘, 데이터 타입이 지정된 부분
  2. payload
    데이터가 저장되는 부분
  3. signature
    해당 토큰이 변조 되지 않은 정상 토큰임을 확인 할 수 있는 부분.

JWT는 비밀 키를 몰라도 복호화(Decode, 해독)이 가능하다. 즉, 변조가 어려운 것이지, 데이터의 비밀을 보장하는 것이 아니다. 그러므로 중요한 정보를 넣지 말자.

쿠키/세션은 데이터를 교환하고 관리하는 방식이지만, JWT는 단순히 데이터를 표현하는 방식일 뿐이다.

JWT로 만든 데이터를 브라우저로 보내도, 쿠키처럼 자동으로 저장되지는 않지만, 변조가 거의 불가능하고, 서버에 데이터를 저장하기 때문에, 서버를 sateless로 관리할 수 있다.

Statless vs Stateful

  • Staeless 무상태
    서버가 언제 죽고, 살아나든 같은 동작을 한다.
  • Stateful 상태 보존
    서버가 죽고, 살아날 때 조금이라도 동작이 다르다.

JWT 코드

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를 뱉는다.

왜 쿠키가 아니라 JWT인가?

  • 쿠키는 변조가 가능하다.
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에 할당한다. = 서버에서 만든 값인지 아닌지 인증 할 수 있다.

참조한 페이지

PUT 과 PATCH 의 차이

profile
node 개발자

0개의 댓글