토큰 사용을 위한 라이브러리 설치
: CMD> npm i jsonwebtoken --save
라이브러리 사용을 위한 객체생성
: const jwt = require('jsonwebtoken');
외부(다른파일)에서도 사용할수있게 modul.exports로 만듦.
: 이때 auth.js 해당 페이지에서도 사용할수있게 객체도 생성해줌
: => const self = module.exports = { }
securityKEY
: salt값, 토큰값을 가공할때 KEY가 되는 값
options
5-1. algorithm
: 알고리즘 명, 메뉴얼대로 HS256으로 함
5-2. expiresIn
: 만료기간, 10m = 10분, 10h = 10시간
5-3. issuer
: 발행자, 임의로 ds라고 함
checkToken
: 프론트엔드에서 오는 토큰의 검증부분
6-1. 토큰은 headers에 담겨서 넘어옴 key는 auth
: postman 적용 시 headers에 auth라는 이름으로 로그인 할때 발급되는 토큰값을 넣음
6-2. 토큰이 있느냐 없느냐
: if (token === null)
6-3. 본격 검증
: 발행시 sign
<=> verify
검증시
: 이 시점(토큰복원)에 오류가 가장 많이 난다.
: 오류는 모두 catch로 간다.
6-4. 토큰이 정확한가
: 로그인 할때 토큰 발행함
: 발행할때 토큰에 넣은 USERID, USERNAME키가 존재하는지 확인
: 없다면 '토큰복원실패'
: 토큰을 복원verify
해서 sessionData에 담음
: const sessionData = jwt.verify(token, self.securityKEY);
6-5. 모든 조건을 통과했으면 routes에서 사용할수 있도록 body안에 해당 값을 담아서 전달(next();
)
: req.body.USERID = sessionData.USERID;
: req.body.USERNAME = sessionData.USERNAME;
catch에서 잡힌 오류
: jwt에서 제공하는 오류메세지를 로그화시켜서 쉽게 파악할수 있도록 한다.
7-1. 토큰인증실패
: if(e.message === 'invalid signature') { }
7-2. 토큰시간만료
: if(e.message === 'jwp expired') { }
7-3. 유효하지않은토큰
: if(e.message === 'invalid token') { }
7-4. 이밖의 메세지 = '유효하지않은토큰'
const jwt = require('jsonwebtoken');
//
// module.exports = { }
const self = module.exports = {
// 토큰 발행 salt값
securityKEY : 'aro9515',
// 토큰 발행에 필요한 옵션들
options : {
algorithm : 'HS256',
expiresIn : '20m',
issuer : 'ds',
},
// 프론트엔드에서 오는 토큰 "검증" 부분
// 검증!
checkToken : async(req,res,next) => {
try {
const token = req.headers.auth; // 키는 auth;
// 1. 토큰이 있냐없냐
if (token === null) {
return res.send({status:0, result:'토큰없음'});
}
// 발행시 sign <=> verify 검증시
// 발행된 토큰, 보안키
// 이 시점 (토큰복원)에 오류가 가장 많이 난다.
// 오류는 모두 catch로 간다
const sessionData = jwt.verify(token, self.securityKEY);
// 2. 토큰이 정확하냐
// USERID, USERNAME키가 존재하는지 확인
// 발행할때 이렇게 넣었기 때문.
if (typeof sessionData.USERID === 'undefined') {
return res.send({status:0,result:'토큰복원실패'})
}
if (typeof sessionData.USERNAME === 'undefined') {
return res.send({status:0,result:'토큰복원실패'})
}
// 위의 if문을 다 통과했으면 완료된거
// routes/member.js에서 사용가능하도록 전달
req.body.USERID = sessionData.USERID;
req.body.USERNAME = sessionData.USERNAME;
// routes/member.js로 전환
next();
} catch (e) {
console.error(e);
if(e.message === 'invalid signature') {
return res.send({status:-1,result:'토큰인증실패'})
}
if(e.message === 'jwp expired') {
return res.send({status:-1,result:'토큰시간만료'})
}
if(e.message === 'invalid token') {
return res.send({status:-1,result:'유효하지않은토큰'})
}
return res.send({status:-1,result:'유효하지않은토큰'})
}
}
}
토큰 라이브러리 사용
: const jwt = require('jsonwebtoken');
/token/auth.js 사용
: 변수명은 auth로 한다.
: const auth = require('../token/auth');
auth.checkToken
: auth.js에서 module.exports한 메소드를 불러와서 사용한다.
: 토큰 검증 후 복원해서 USERID와 USERNAME을 전달해주는 역할
토큰에서 추출한 USERID를 sessionID로 정의
프론트에서 전달된 값인 name과 age도 받아둠
변경할 항목을 조회한다
: 조건은 _id = sessionID
조회한 항목은 Member타입(entity)으로 넘어오며, 수정도 여기서 한다.
: 변수명은 Member1로 받는다.
: member1 = sessionID로 조회한(현재 로그인 한 사용자의 토큰을 복원해서 얻어낸 USERID로 조회한) 항목들
프론트에서 전달받은 name과 age를 변경하여 member1에 담는다.
member1을 save();
한다. = 덮어씌운다. (수정)
: const result = await member1.save();
// 127.0.0.1:3000/member/update
router.put('/update', auth.checkToken, async function(req, res, next) {
try {
const sessionID = req.body.USERID; // 토큰에서 추출
const name = req.body.name; // 전달된값
const age = req.body.age; // 전달된값
// 아이디에 해당하는 값을 조회
var member1 = await Member.findOne({_id : sessionID});
member1.name = name;
member1.age = age;
const result = await member1.save();
if(result._id != '') {
return res.send({status:200})
}
return res.send({status:0})
} catch (e) {
console.error(e);
return res.send({status:-1})
}
});
const jwt = require('jsonwebtoken');
const auth = require('../token/auth');
const Member1 = await Member.findOne({_id:sessionID, password:hashPw});
const hashPw1 = crypto.createHmac('sha256', sessionID,).update(req.body.pw1).digest('hex');
if (Member1.password === hashPw) { }
save();
한다.Member1.password = hashPw1
const result = await Member1.save();
// 127.0.0.1:3000/member/updatepw
router.put('/updatepw', auth.checkToken, async function(req, res, next) {
try {
const sessionID = req.body.USERID; // 토큰에서 추출
// console.log('sessionID ===> ',sessionID);
const hashPw = crypto.createHmac('sha256', sessionID,).update(req.body.pw).digest('hex');
const hashPw1 = crypto.createHmac('sha256', sessionID,).update(req.body.pw1).digest('hex');
// console.log('hashPw ===> ', hashPw);
// console.log('hashPw1 ===> ', hashPw1);
const Member1 = await Member.findOne({_id:sessionID, password:hashPw});
// console.log('/updatepw/Member1 ===> ',Member1);
if (Member1.password === hashPw) {
// console.log('암호일치');
Member1.password = hashPw1
const result = await Member1.save();
// console.log('/updatepw/result ===> ',result);
return res.send({status:200});
}
console.log('암호틀림');
return res.send({status:0});
} catch (e) {
console.error(e);
return res.send({status:-1});
}
});
const jwt = require('jsonwebtoken');
const auth = require('../token/auth');
query
)const result = await Member.deleteOne(query);
const sessionID = req.body.USERID;
const hashPw = crypto.createHmac('sha256', sessionID,).update(req.body.pw).digest('hex');
// 127.0.0.1:3000/member/delete
router.delete('/delete', auth.checkToken, async function(req, res, next) {
try {
const sessionID = req.body.USERID; // 토큰에서 추출
// console.log('sessionID ===> ',sessionID);
const hashPw = crypto.createHmac('sha256', sessionID,).update(req.body.pw).digest('hex');
const query = {$and : [{_id : sessionID, password: hashPw}]};
const result = await Member.deleteOne(query);
console.log('/delete/result ===> ',result);
if (result.deletedCount === 1) {
return res.send({status:200});
}
return res.send({status:0});
} catch (e) {
console.error(e);
return res.send({status:-1});
}
});