본문 바로가기
프로그래밍/database

[220303] npm과 jwt을 활용해서 로그인 확인 기능 만들기

by 한코코 2022. 3. 3.

[목록]

1.   npm 명령어로 서버 시작하기

2.   코드를 자동으로 갱신해주는 nodemon

3.   로그인시 jwt 생성하기

4.   로그인 확인을 위해 쿠키에서 jwt 정보 추출하기

5.   try/catch문을 통해 응답코드 짜기

 


 

1.   npm 명령어로 서버 시작하기

서버를 시작하는 node server의 의미

node로 된 명령어를 쓸건데, server.js파일을 실행할거란 명령문.

명령문을 이용하면 다른 명령어를 사용해서 서버를 시작할 수 있다.

 

npm run start

npm 스크립트 안에 있는 start 명령어를 run(실행)할게.

start 명령어는 node server과 연결되어있기때문에 결과적으로 서버가 시작된다.

 


 

2.   서버를 자동적으로 갱신해주는 nodemon

서버를 껐다 켜는 것을 반복하지 않아도, 서버가 수정되면 자동 갱신되게 해주는 라이브러리 노드문.

설치해주고나면 nodemon server를 입력해도 서버가 실행이 된다.

npm install -g nodemon

package.json에 명령어 dev를 추가해주면 npm run dev로도 서버가 시작이 된다.

코드를 수정하고 저장기능을 수행하면 자동으로 바뀐 코드를 인식해 자동갱신이 된다.

단점 : nunjucks는 바뀌어도 인식을 잘 못함.

해결책 : npm install chokidar로 설치watch:true를 해주면 nunjucks를 인식한다.

nunjucks.configure('views',{
    express:app,
    watch : true
})

 

 

생략되어 있어서 인식하지 못한 status

res.send 사이에 status(200)가 숨어있다. 

항상 있는 상태(status)값이라서 생략되어있던것.

꼭 200이 아니여도 된다. 임의 할당이 가능하다.

res.status(200).send('도착!')
res.send('도착!')

status(300)을 입력해도 잘 실행되고, status가 300으로 뜬다.

 


 

3.   로그인시 jwt 생성하기

jwt생성을 함수로 처리하기

//jwt토큰을 생성할 함수를 담은 jwt.js
const crypto = require('crypto')
const salt = 'ingoo'

//token 생성 함수
function createToken(state){
    const header = {alg:'HS256',typ:'JWT'}
    const payload = { ...state }
    
    const encodingHeader = encoding(header)
    const encodingPayload = encoding(payload)
    const signature = createSignature(encodingHeader,encodingPayload)

    return `${encodingHeader}.${encodingPayload}.${signature}`
}

//인코딩 함수
function encoding(value){
    return Buffer.from(JSON.stringify(value)).toString('base64')
}

//서명 생성 함수
function createSignature(header,payload){
    const encoding = `${header}.${payload}`
    const signature = crypto.createHmac('sha256',salt)
                        .update(encoding).digest('base64')
                        .replace(/[=]/g,'')
    return signature
}

module.exports = {
    createToken,
    createSignature
}
// /login에서 post라우터 관리를 하는 server.js
app.post('/login',(req,res)=>{
    let {userid,userpw} = req.body
    const [item] = user.filter(v=>v.userid===userid && v.userpw===userpw)
    try{
        if(item===undefined) throw new Error ('아이디 존재하지 않음')

        const payload = {
            userid : item.userid,
            userpw : item.userpw,
            level:1 
        }

        const token = createToken(payload)
        console.log(token)
        res.setHeader('Set-cookie',`AccessToken=${token};
                                    HttpOnly; Secure; Path=/`)
        //자바스크립트로 조작 못하게 HttpOnly; Secure;
        //모든 path에서 응답하도록 Path=/;
        
        res.send('도착')
    } catch(e){
        console.log(e)
        res.status(500).send('실패')
    }
})

 

4.   로그인 확인을 위해 쿠키에서 jwt 정보 추출하기

쿠키를 가지고있다가 주는 주체 = 클라이언트

//미들웨어 작성을 위한 auth.js을 가져온 server.js
const {auth} = require('./middleware/auth')

app.use(auth) //미들웨어 사용코드
//미들웨어 작성을 위한 auth.js
exports.auth = (req,res,next) =>{
    console.log(req.headers)
    next()
}

auth.js에서 req.headers값.  cookie 값이 잘 들어가 있는 것을 확인할 수 있다.

 

 

const {createSignature} = require('../utils/jwt')

exports.auth = (req,res,next)=>{
    //시작하자마자 실행하게 설정
    const cookies = req.headers.cookie
    const [[,token]] = cookies.split(';')
                        //빈칸을 삭제하고 =기준으로 나눔
                        .map(v=>v.trim().split('='))
                        .filter(v=>{ return v[0]=='AccessToken' })

    try {
        //토큰 유효성 검사
        //token을 .기준으로 헤더 페이 서명 가져옴
        const [header,payload,sign] = token.split('.')
        //가져온 헤더 페이 가지고 새 서명 만듬
        const signature = createSignature(header,payload)
        //새 서명이랑 기존 서명이랑 비교함
        // console.log(signature)
        if(signature!==sign) throw new Error('Token error')
        //페이에 대한 내용을 디코딩해서 가져온다.
        const user = JSON.parse(Buffer.from(payload,'base64')
        			.toString('utf-8'))
        //req에 user을 추가해서 보냄
        req.user = {
            ...user
        }
        
        next()
    } catch(e){
        res.send('토큰 조작하셨군요?')
        next()
    }
}

 

 


 

5.   try / catch문을 통해 응답코드 짜기

성공시 try 안에 있는 코드를 실행시키고, 에러발생시 catch 안에 있는 코드가 실행된다.

try 코드를 진행하다 맞지 않는 값이 나오면 new Error코드를 사용해 강제로 에러로 보낼 수 있다.

어떤 코드를 실행하다가 에러가 발생하면 무조건 catch 코드를 실행하기 때문에 if else문보다 에러대응에 효율적이다.

try{
    if(signature !== sign) new Error('에러 발생')
	console.log('성공')
}
catch (error) {
	console.log('에러발생시 이 메세지 출력')
}

댓글