이번에는 기존에 만든 jwt토큰을 이용해서 인증절차를 만들 수 있도록 할 예정이다.
jwt 사용해서 user조회하기 req.header."Authorization"을 사용할것이다.
먼저 헤더에 토큰 담는걸 연습한 후에 시도해보자
기존에 body에서 user_id를 받던걸 jwt쿠키에 id를 추가해서 가져올 수 있도록 구현함
let recivedJWT = req.headers["authorization"];
let decodedJWT = jwt.verify(recivedJWT, process.env.SECRTE_KEY)
위에껄 함수로 만든다.
function ensureAuthorization(req) {
let recivedJWT = req.headers["authorization"];
let decodedJWT = jwt.verify(recivedJWT, process.env.SECRTE_KEY)
return decodedJWT
}
// 클린코드에서는 이렇게 여러곳에 사용되는건 전체 코드를 한번만 읽을 수 있도록 아래에 나두란다.
// 이름 같은건 동사를 이용하고, 직관적인 이름을 사용하는게 좋다.
TokenExpiredError: jwt expired
JWT 토큰 유효기간이 지나서 500 에러가 났다. 이걸 핸들링 할 수 있어야한다.
원래는 예상 가능한 에러에 대해서 if...else를 사용하는데, 예외(개발자가 생각하지 못한 에러)에 대한 처리를 할 때는 try...catch문을 사용할 수 있다.
이걸 이용해서 유효기간이 지난 토큰이라면 '로그인(인증) 세션(유지되는 상태가)이 만료되었습니다. 다시 로그인 하세요.'라는 메세지를 띄울 수 있도록 만들어 줄것이다.
JWT 예외처리
드디어!! try...catch를 사용한다.
개발자가 예상하지 못한 에러(실수, 사용자 입력을 잘못한 것, 디비가 응답을 잘못한 경우...등등)를 처리하는 문법
예상하지 못한 에러보다는 프로그램에서 일어나는 수 많은 에러들
if...else로 커버하지 못하는 것들에 대한 걸 다룰때 사용한다.
let string = '{"num1":1'
try{
username; // ReferenceError
let json = JSON.parse(string); //SyntaxError
console.log(json)
}catch(err){
console.log(err);
}
자스가 고대 개발자들의 노고를 보고,"내장" 에러 객체를 만들어 뒀다.
JWT라는 모듈에서 제공하는 에러 객체도 있고,
여러분들이 직접 만들어쓸 수 있는 에러객체도 있다.
// ReferenceError: username is not defined
// ...
console.log(err.name); // ReferenceError
console.log(err.message); // username is not defined
에러를 발생시키는 연산자...?
// throw 에러 객체
// ex.throw SyntaxError();
let string = '{"num1":1}'
try{
let json = JSON.parse(string);
if(!json.name){
throw new SyntaxError("입력 값에 이름이 없습니다.")
} else {
console.log(json.name);
}
let name = json.name;
console.log(name);
}catch(err){
console.log(err.name);
console.log(err.message);
console.log(err)
}
node:_http_outgoing:699
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
이건 res를 2번 보내기에 생기는 일,
해당 함수를 불러오는 로직에서 res를 변수에 넣었기 때문에, 2번 보내게 되는 것이다.
이때 err를 반환하게 변경하고 다음과 같이 로직에 코드를 추가하여 수정해줄 수 있다.
const getCartItem = (req,res)=>{
const {selected} = req.body;
let authorization = ensureAuthorization(req, res)
if ( authorization instanceof jwt.TokenExpiredError){
return res.status(StatusCodes.UNAUTHORIZED).json({
"message": "로그인 세션이 만료되었습니다. 다시 로그인해주세요"
})
}
//...
//...
function ensureAuthorization(req,res) {
try{
let recivedJWT = req.headers["authorization"];
console.log(recivedJWT)
let decodedJWT = jwt.verify(recivedJWT, process.env.SECRTE_KEY)
return decodedJWT
} catch(err){
console.log(err.name);
console.log(err.message);
return err
// return res.status(StatusCodes.UNAUTHORIZED).json({
// "message": "로그인 세션이 만료되었습니다. 다시 로그인해주세요"
// })
}
}
근데 이게 또 다른 에러는 찾아주지 않는다.
그렇기에 if문을 추가하여 다른 에러에 대해서도 예외처리를 해주어야한다.
다른 파일에서도 사용하게 되기에, 이걸 모듈화 해주었다.
const jwt = require("jsonwebtoken")
const dotenv = require('dotenv')
dotenv.config();
const ensureAuthorization = (req,res) => {
try{
let recivedJWT = req.headers["authorization"];
let decodedJWT = jwt.verify(recivedJWT, process.env.SECRTE_KEY)
return decodedJWT
} catch(err){
console.log(err.name);
console.log(err.message);
return err
}
}
module.exports = ensureAuthorization