[DevCamp] Express 인증 & 인가 - JWT, .env

동건·2025년 2월 28일
0

DevCamp

목록 보기
20/85

📌 Express 인증 & 인가 - JWT, .env

오늘은 JWT.env 를 사용해 보안을 신경쓴 코드를 학습했다.


1. 인증 VS 인가

✅ 인증 (Authentication)

  • 로그인 과정
  • 예: 쇼핑몰에서 상품을 볼 때는 인증 불필요하지만, 구매하려면 로그인 필요

✅ 인가 (Authorization)

  • 권한 부여 과정
  • 예: 같은 사이트에서도 관리자는 모든 기능 접근 가능하지만, 일반 사용자는 일부 기능만 접근 가능

2. 쿠키 vs 세션 vs JWT

  • 클라이언트가 데이터를 저장하고 요청 시 서버에 전송
  • 장점: 서버 저장 공간 절약, RESTful한 구조 유지 가능
  • 단점: 보안 취약

📌 세션 (Session)

  • 서버에 데이터를 저장하고 클라이언트는 세션 ID만 보관
  • 장점: 쿠키보다 보안이 강함
  • 단점: 서버 저장 공간 사용, RESTful X

🔐 JWT (Json Web Token)

  • JSON 형태로 정보를 암호화하여 저장하는 토큰 방식
  • 장점: 보안 강함, Stateless (서버 상태 저장 불필요), 서버 부담 감소
  • 구조:
    • 헤더: 암호화 알고리즘 및 타입 정보
    • 페이로드: 사용자 정보 (비밀번호 X)
    • 서명: 데이터 변조 여부 확인

✅ JWT 인증 절차

  1. 사용자가 로그인 정보를 입력
  2. 서버에서 유효성 검사를 수행하고 JWT 발급
  3. 클라이언트가 JWT를 저장 (쿠키 또는 로컬스토리지)
  4. 이후 요청마다 JWT를 포함해 인증된 사용자임을 증명
  5. 서버는 JWT의 서명을 검증하여 유효한 요청인지 판단

3. .env 환경변수 관리

✅ .env 개념

  • 서버에서 중요한 환경 변수(포트 번호, DB 계정 등)를 별도 파일로 관리
  • 깃허브에 업로드되면 안 됨

✅ dotenv 설정 방식 차이

// 방식 1
const dotenv = require('dotenv');
dotenv.config();
console.log(`${process.env.PRIVATE_KEY}`); // 문자열 보간 필요
// 방식 2
require('dotenv').config();
console.log(process.env.PRIVATE_KEY); // 바로 사용 가능

차이점
1. const dotenv = require('dotenv');을 선언한 경우, dotenv.config();를 호출해야 환경변수가 로드됨.
2. require('dotenv').config();을 사용하면 즉시 환경변수가 설정됨.
3. 첫 번째 방식에서는 템플릿 리터럴 사용 시 ${process.env.KEY}로 접근해야 함.


4. Express 인증 기능 적용 (users.js)

✅ 로그인 기능

router.post(
    '/login',
    [
        body('email').notEmpty().isEmail().withMessage("이메일을 확인해주세요."),
        body('password').notEmpty().isString().withMessage("패스워드를 확인해주세요."),
        validate
    ],
    (req, res) => {
        const { email, password } = req.body;
        let sql = `SELECT * FROM users WHERE email = ?`;
        conn.query(sql, email, function (err, results) {
            if (err) {
                return res.status(400).json({ message: err });
            }
            let loginUser = results[0];
            if (loginUser && loginUser.password === password) {
                const token = jwt.sign({
                    email: loginUser.email,
                    name: loginUser.name
                }, process.env.PRIVATE_KEY, {
                    expiresIn: '1h',
                    issuer: "Donggeon"
                });
                res.cookie('token', token, { httpOnly: true });
                res.status(200).json({ message: `${loginUser.name}님 로그인 되었습니다.` });
            } else {
                res.status(404).json({ message: "이메일 또는 패스워드가 틀렸습니다." });
            }
        });
    }
);

개선된 점
1. jwt.sign()을 사용해 로그인 시 JWT 생성 및 쿠키에 저장.
2. httpOnly 옵션으로 XSS 공격 방지.


🔨 5. TIL

오늘 학습한 내용 중 dotenv 를 사용하면서 많이 애를 먹었다.
정말 많은 시간을 할애해서 원인을 찾아봤는데

const dotenv = require('dotenv');
dotenv.config();
...
require('dotenv').config();

이 2개가 차이가 있었다는 점이다.

위처럼 하니까 process.env.PRIVATE_KEY 를 사용하지 못하고
${process.env.PRIVATE_KEY} 이렇게 문자열로 바꿔줘야만 사용 가능했다.

구글링 해본 결과 문자열로 지정해서 하는건 임시적인 해결이라
권장하지는 않는다고 했다.

이렇게 에러를 직접 구글링 해보고 팀원과 얘기를 나눠보면서
해결방안을 찾아보니 괜히 뿌듯함을 느끼고 재미를 느꼈다.

profile
배고픈 개발자

0개의 댓글