20250228학습 (next(), 쿠키, 세션, JWT)

airbus·2025년 2월 28일

프로그래머스

목록 보기
28/93

next()

// channels3.js
//========== validate
const validate = (req, res) => { // const err 부터 ~ return 문까지 중복으로 쓰임
    const err = validationResult(req) // 중복되는 내용을 vlidate 변수에 담아 함수를 하나의 모듈로서 사용


    if (!err.isEmpty()) { // 오류가 있으면 실행
        return res.status(400).json(err.array())
    }
}

//==========
router
    .route('/')
    .get(
        [
            body('userId').notEmpty().isInt().withMessage('숫자 입력 필요') //검증내용
            validate // 검증확안, 오류처리
        ]
        , (req, res) => { ~ }

위의 코드를 실행하면 요청만 보내지고 응답을 기다리기만 하는 오류가 발생합니다.

body의 .notEmpty 이런부분은 body로 받아온 userId가 지켜야 하는 규칙을 설정한 것, 실제로 검증을 확인하고 처리하는 것은 validate에서 일어납니다.

오류가 발생하지 않았다면 다음에 무엇을 할지 알아야 하는데, 무엇을 해야하는지 정해지지 않은 상태. -> 계속 응답대기

const validate = (req, res, next) => { // 매개변수에 next를 추가 - next 함수를 받아오는 역할
    const err = validationResult(req)

    if (err.isEmpty()) {
        return next() // 다음 함수를 찾아가라는 의미 / 다음 할 일 (미들웨어, 함수)
    } else {
        return res.status(400).json(err.array())
    }
}

매개변수에 next를 추가하여 next함수를 받아오게 만들고,
if문에서 next()함수를 return 하여 다음 미들웨어를 실행하게 정해주었습니다.

else문은 오류발생시 상태코드400과 에러내용을 처리합니다.
추가로, 기존의 if문이 이중부정문이었던 것을 긍정/부정의 형식으로 수정하였습니다.
ex) !err.isEmpty() 에러가 없지 않을 때 실행
ex) err.isEmpty() 에러가 없을 때 실행


미들웨어 보충

미들웨어 : 요청과 응답의 중간(middle)의 위치에서 동작하기에 미들웨어라고 합니다.
요청과 응답을 컨트롤하고, 부적절한 요청을 판단합니다.

주소가 없을 때 : app.use((req, res, next() => {}) 는 모든 요청에서 실행
실행 주소가 있을 때 : app.get('/', (req, res, next() => {}) get메서드의 / 요청에서만 실행
p.246 참고 할 것 (node.js)

쿠키와 세션

인증과 인가

인증 (Authentication)
무언가를 확인하거나 확증하는 행위.
ex) 로그인하여 해당 사이트의 유저인 것을 인증

인가 (Authorization)
어떠한 행위에 대한 허가.
ex) 사이트의 회원이지만, 관리자페이지에 접근할 권한을 인가받지 않은 경우, 접속 불가. (인증은 되었으나, 인가받지 못함)

쿠키

사이트에 접속하여 로그인 한 경우, 페이지를 이동하거나 할 때 로그인 상태를 유지하고 있을 수 있는 이유는 쿠키 덕분입니다.
클라이언트에서 요청을 보낼때 쿠키와 함께 서버에 보내지기 때문입니다.

쿠키의 동작원리
ex) 로그인

  • 클라이언트가 서버에 로그인 요청을 보냈을 때 서버는 쿠키와 함께 응답을 보냅니다.
  • 해당 쿠키는 서버에서 만들어 클라이언트에게 보내고, 이후부터는 클라이언트가 요청을 보낼 때마다 쿠키를 이용하여, 사용자를 파악합니다. //받은 쿠키는 웹 브라우저가 메모리에 저장해둡니다.
  • 쿠키는 요청의 헤더부분에 담겨 보내집니다.
  • 쿠키는 중간에 가로채지면 정보가 노출될 수 있습니다. 보안이 취약합니다.
  • 서버에 저장하지 않기에 서버저장 공간이 절약됩니다. Stateless(상태를 저장하지 않음) => RESTful

세션

  • 서버에 사용자 정보를 저장합니다.
  • 서버와 클라이언트가 쿠키대신 세션아이디로만 통신합니다. (쿠키에 세션아이디를 담아서 통신)
  • 쿠키에 비해 보안이 좋은 편이지만, 서버에 저장되어 부담이 될 수 있습니다.

JWT

JSON Web Token
JSON 형태의 데이터를 안전하게 전송하기 위해 웹에서 사용하는 토큰입니다.
토큰은 인증기능과, 권한기능이 있습니다.

쿠키와 세션의 단점을 보완합니다.

  • 암호화가 되어있어 보안에 강합니다.
  • 서버가 클라이언트의 상태를 저장하지 않습니다. (Stateless) -> 서버 부담이 낮음

설치
npm 에서 'jsonwebtoken'을 검색하여 설치 링크
npm i jsonwebtoken

const jwt = require('jsonwebtoken'); // jwt 모듈
const dotenv = require('dotenv'); // dotenv 모듈
dotenv.config(); // dotenv 설정 사용

// 로그인
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) {
                    console.log(err)
                    return res.status(400).end()
                }
                var loginUser = results[0];

                if (loginUser && loginUser.password == password) {
                    // token 발급
                    const token = jwt.sign({
                        emial : loginUser.email,
                        name : loginUser.name
                    }, process.env.PRIVATE_KEY_LOGIN, {
                        expiresIn : '5m',// 토큰만료시간
                        issuer : "kim" //
                    });
                    //쿠키 
                    res.cookie("token", token, {
                        httpOnly: true
                    }) //쿠키에는 여러가지 값을 담을 수 있고, token 상자안에 token 을 담아 보냄
                    console.log(token);
                    res.status(200).json({
                        message: `${loginUser.name}님 로그인 되었습니다.`
                    })
                } else {
                    res.status(403).json({ // 403 인증거부 
                        message: "이메일 또는 비밀번호가 틀렸습니다."
                    })
                }
            }
        )
    })

ex)
res.cookie

  • "token" : 쿠키의 이름 입니다.
  • token : 쿠키에 저장되는 값 입니다.
  • httpOnly : true : XSS 공격을 방지합니다.
    false = js에서 접근이 가능하며, 쿠키도 공격대상이 됩니다.
    true = http api로만 쿠키 접근이 가능합니다.

JWT 구조

JWT는 암호화가 되어있습니다.
jwt.io에서 링크 그 구조를 확인 할 수 있습니다.

HEADER, PAYLOAD, VERIFY SIGNATURE 3부분으로 구조가 나뉩니다.

  • HEADER : 토큰에 사용된 암호화 알고리즘과, 토큰의 타입(형태)가 담겨있습니다.
  • PAYLOAD : 데이터가 담깁니다.
  • VERIFY SIGNITURE : 검증의 역할을 합니다. 서명/페이로드의 값이 변경되면 SIGNITURE값 통째로 변경됩니다.
    = 같은 알고리즘으로 복호화하여 임의로 변경하려해도 안전합니다.

ex)
jwt.sign (payload, secretKey, options)

  • jwt.sign({...}) : payload입니다. 토큰에 들어가는 데이터입니다.
  • process.env.PRIVATE_KEY_LOGIN : secretKey입니다. dotenv를 사용하여 키를 직접적으로 노출시키지 않았습니다.
    직접적인 키입력 대신 .env파일에서 PRIVATE_KEY_LOGIN의 값을 가져옵니다.
  • expiresIn : 토큰 만료시간 입니다.
  • issure : 토큰 발급자입니다.

.env

환경변수로 .env 파일에 설정 값을 보관합니다.

  • 개발시 외부에 유출되면 안되는 중요한 환경 변수(포트넘버, 데이터베이스 계정, 암호키 등)를 따로 관리 하기 위한 파일입니다.
    .gitignore 에 추가하여 깃허브에서 제외합니다.
  • 확장자와 파일명 모두 .evn 로 동일합니다.
  • 프로젝트 최상위 패키지에 존재해야 합니다.
  • 스네이크 형식으로 작성합니다.
  • 주석은 # 를 사용합니다.

설치
npm에서 'dotenv'을 검색하여 설치 링크
npm i dotenv

0개의 댓글