Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

ddodoi 님의 블로그

6주차-파트03: next(), 쿠키 vs 세션 vs JWT, .env파일 본문

웹풀스택 일일정리

6주차-파트03: next(), 쿠키 vs 세션 vs JWT, .env파일

ddodoi 2024. 9. 27. 16:12

CHAPTER 1. next()

 

channel.js 코드를 수정하면서 우리는 각 기능별로 다음 error를 진단하는 코드 줄이 공통된다는 것을 알았다. 효율성을 위해 아래 코드를 변수에 담아 미들웨어(모듈화)로 사용해보자.

 

 

 

변수 validate안에 error를 검사하는 함수를 넣어준다. next()함수를 사용하여 만약 error가 발생하지 않을경우 다음 콜백함수로 넘어갈 수 있도록 해준다.

const validate = (req, res, next) => {
    const err = validationResult(req)

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

 

 

 

 

 

 

그다음 전체 재널 조회 기능에서 다음과 같이 사용한다. 

router
    .route('/')

    //채널 전체 조회
    .get( 
        [body('user_id').notEmpty().isInt().withMessage('숫자 입력 필요'),
        validate],
    (req, res, next)=>{
        const err = validationResult(req)

        if (!err.isEmpty()){
            return res.status(400).json(err.array())
        }
        
        let {user_id} = req.body

        let sql =  `SELECT * FROM posts WHERE user_id =?`
        conn.query(sql, user_id,
            function(err,results){
                if (err){
                    console.log(err)
                    return res.status(400).end()
                }
                if (results.length){
                    res.status(200).json(results)
                    }
                else {
                    notFoundChannel(res)
                    }
        })
    })

 

 

 

 

CHAPTER 2. 인증과 인가, 쿠키 vs 세션 vs JWT

 

✔️인증(=로그인) 

Authentication

웹사이트에 가입된 유저임을 증명,

관리자든 고객이든 인증을 통해 사이트에 가입된 사용자라는 걸 증명 하는 것

 

//세션 : (로그인이 되어 있는) 상태

 

 

 

✔️인가

Authorization

인증 후 특정 페이지에 접근 권한이 있는지 확인하는 것

ex) 같은 사이트 내에 관리자/ 고객에 따라 접근할 수 있는 페이지가 다르다.

 

 

 

 

 

 

쿠키

웹에서 서버와 클라이언트가 주고받는 데이터 중 하나로, 웹서버가 쿠키를 생성하여 브라우저에게 주면, 브라우저가 자기 메모리에 저장한 뒤 같은 웹서버 방문시 쿠키를 들고 요청하러 간다.

 

1) 로그인시 -> 서버가 쿠키를 구워준다.

2) 사용자 <-> 서버가 쿠키를 핑퐁

 

장점:

- 서버가 정보를 저장하지 x  => 서버의 저장 공간을 아낄 수 있다

   Stateless(상태를 저장하지 않는다) => RESTful

 

단점 : 보안에 취약

 

 

 

✅세션

네트워크 분야에서 컴퓨터와 사용자 간의 대화나 송수신 연결 상태를 의미하는 보안적인 다이얼로그와 시간대.

쿠키의 단점을 보완한다.

1) 로그인 -> 서버가 금고를 만들어 정보를 저장하고 그 금고의 번호를 준다.

2) 사용자 <-> 서버가 금고 번호만 가지고 대화

 

장점 :

- 보안이 비교적 좋다.

 

단점:

- 서버가 저장을 한다 => 서버의 저장 공간 차지

  Stateless x

 

 

 

JWT(JSON Web Token)

 

json형태의 데이터를 안전하게 전송하기 위한 (웹에서 사용하는) 토큰

=토큰을 가진 사용자가 "증명"을 하기 위한 수단

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

 

cf. 토큰:(인증용) 입장 가능한 유저다/ (인가용)관리자 권한& 일반 유저 권한

 

장점:

- 보안에 강하다 <= "암호화"가 되어있다.

- HTTP특징을 잘 따랐다= Stateless하다 <= 서버가 상태를 저장하지 않는다.

- 서버 부담 줄여줄 수 있다.

 

cf. 토큰을 발행하는 서버를 따로 만들어 줄 수도 있다.

 

 

구조:

  • 헤더 : 토큰을 암호화하는데 사용한 알고리즘(=토큰의 형태(jwt))
  • 페이로드: 사용자 정보(이름, 주소, 핸드폰,........)
  • 서명: 만약 페이로드 값이 바뀌면, 이 서명값 통째로 바뀌기 때문에 우리는 jwt를 믿고 쓸 수 있다.

 

 

 

 

 

 

 

CHAPTER 3. JWT 구현해보기

 

JWT를 사용할려면 npm에서 외부 모듈로 다운받을수 있다.

https://www.npmjs.com/package/jsonwebtoken

 

jsonwebtoken

JSON Web Token implementation (symmetric and asymmetric). Latest version: 9.0.2, last published: a year ago. Start using jsonwebtoken in your project by running `npm i jsonwebtoken`. There are 31480 other projects in the npm registry using jsonwebtoken.

www.npmjs.com

 

 

 

다음은 jwt토큰의 구조이다. Header, payload, signature로 이루어져 있다.

 

다음 코드를 실행시켜보자.

var jwt = require('jsonwebtoken');   //jwt모듈 소환


//서명 = 토큰 발행
var token = jwt.sign({ foo: 'bar' }, 'shhhhh');   
//토큰 생성 = jwt 서명을 했다(페이로드, 나만의 암호키) + SHA256
console.log(token)

//검증
//만약 검증에 성공하면, 페이로드 값을 확인할 수 있음
var decoded = jwt.verify(token,'shhhhh');
console.log(decoded);

 

 

 

다음은 위 코드를 서로 다른 시간에 걸쳐 2번 실행시킨 결과이다. iat는 issued at의 약자로 토큰이 발행된 시간을 초단위로나타낸 것이다. 다른 시간대에 걸쳐 2번 실행시켰기 때문에 iat의 값이 각각 다르다.

암호화된 코드는 .을 단위로 헤더, 페이로드, 시그니쳐로 분리된다. 헤더값은 그 값을 수정하지 않는 이상 항상 같으며, 페이로드와 시그니쳐는 시간에 따라 항상 달라진다.

 

 

 

CHAPTER 4. .env

그러나 위 코드처럼 암호키가 코드에 바로 있으면 암호키가 전부 공개되어버린다. 이를 방지하기 위해 .env파일을 이용해보자.

✅.env(environment : 환경 변수 '설정 값')

개발을 하다 포트넘버, 데이터 베이스, 계정, 암호키,...등등 외부에 유출되면 안되는 중요한 변수들을 따로 관리하기 위한 파일

 

cf. 깃허브에 올라가면 안되는 값

 

파일 확장자 : .env

 

프로젝트 파일에 .env파일 생성 후 암호키를 적어주자. env파일은 환경변수 파일이므로 프로젝트 최상위 패키지에 존재해야한다.

 

 

 

이제 .env안 암호키 값을 이용할 수 있도록 jwt-demo.js파일을 바꿔주자.

var jwt = require('jsonwebtoken');   //jwt모듈 소환
var dotenv = require('dotenv');

dotenv.config();

//서명 = 토큰 발행
var token = jwt.sign({ foo: 'bar' }, process.env.PRIVATE_KEY);   
//토큰 생성 = jwt 서명을 했다(페이로드, 나만의 암호키) + SHA256
console.log(token)

//검증
//만약 검증에 성공하면, 페이로드 값을 확인할 수 있음
var decoded = jwt.verify(token, process.env.PRIVATE_KEY);
console.log(decoded);

 

 

 

잘 실행된다.

 

 

 

 

 

 

 

 

CHAPTER 5. 쿠키 사용하기

user.js의 로그인 부분에서 토큰을 발급하고 그 값을 쿠키에 넣도록 설정해보자.

                if (loginUser && loginUser.password == password){
                    //token 발급
                    const token = jwt.sign({
                        email : loginUser.email,
                        name : loginUser.name
                    }, process.env.PRIVATE_KEY)
                    
                    res.cookie("token", token, {
                        httpOnly : true
                    })

 

 

 

쿠키값을 확인해보면 토큰값이 들어감을 알 수 있다.

 

 

 

 

✔️Secure

HTTP

http://localhost:1234/login

 

HTTPS(secure)

https://www.naver.com

 

 

 

 

 

 

cf. httpOnly(= 프론트엔드가 아니라 API호출만 허락할건지?) : XSS공격(프론트엔드 공격 : 웹 브라우저 js 접근 => 공격)

httpOnly가 false일 경우 프론트엔드 환경에서 공격이 들어오면 쿠키도 공격대상이 될 수 있다.

httpOnly가 true일 경우 HTTP  API로만 쿠키에 접근이 가능하다.