통합구현 #3 - Mypage

김형우·2022년 3월 14일
0

mongoose + vue.js

목록 보기
4/15

0. token/auth.js

  1. 토큰 사용을 위한 라이브러리 설치
    : CMD> npm i jsonwebtoken --save

  2. 라이브러리 사용을 위한 객체생성
    : const jwt = require('jsonwebtoken');

  3. 외부(다른파일)에서도 사용할수있게 modul.exports로 만듦.
    : 이때 auth.js 해당 페이지에서도 사용할수있게 객체도 생성해줌
    : => const self = module.exports = { }

  4. securityKEY
    : salt값, 토큰값을 가공할때 KEY가 되는 값

  5. options
    5-1. algorithm
    : 알고리즘 명, 메뉴얼대로 HS256으로 함
    5-2. expiresIn
    : 만료기간, 10m = 10분, 10h = 10시간
    5-3. issuer
    : 발행자, 임의로 ds라고 함

  6. 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;

  7. 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:'유효하지않은토큰'})
        }
    }
}

1. 회원정보수정

  • 로그인 필요 = 토큰 검증
  1. 토큰 라이브러리 사용
    : const jwt = require('jsonwebtoken');

  2. /token/auth.js 사용
    : 변수명은 auth로 한다.
    : const auth = require('../token/auth');

  3. auth.checkToken
    : auth.js에서 module.exports한 메소드를 불러와서 사용한다.
    : 토큰 검증 후 복원해서 USERID와 USERNAME을 전달해주는 역할

  4. 토큰에서 추출한 USERID를 sessionID로 정의

  5. 프론트에서 전달된 값인 name과 age도 받아둠

  6. 변경할 항목을 조회한다
    : 조건은 _id = sessionID

  7. 조회한 항목은 Member타입(entity)으로 넘어오며, 수정도 여기서 한다.
    : 변수명은 Member1로 받는다.
    : member1 = sessionID로 조회한(현재 로그인 한 사용자의 토큰을 복원해서 얻어낸 USERID로 조회한) 항목들

  8. 프론트에서 전달받은 name과 age를 변경하여 member1에 담는다.

  9. 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})
    }
});

2. 암호변경

  • 로그인 필요 = 토큰 검증
  1. 토큰 라이브러리 사용
    : const jwt = require('jsonwebtoken');
  2. /token/auth.js 사용
    : 변수명은 auth로 한다.
    : const auth = require('../token/auth');
  3. auth.checkToken
    : auth.js에서 module.exports한 메소드를 불러와서 사용한다.
    : 토큰 검증 후 복원해서 USERID와 USERNAME을 전달해주는 역할
  4. 수정할 항목 조회
    : 변수명은 Member1
    : const Member1 = await Member.findOne({_id:sessionID, password:hashPw});
    4-1. 조회조건은 토큰에서 추출한 _id와 프론트에서 전달받은값 pw를 해쉬한 hashPw 두개
  5. 조회한 항목의 password를 바꾸면 된다.
    : 이때도 프론트에서 전달받은 새 암호 = pw1도 hash해서 넣어야 한다.
    : 암호니까!
    5-1. const hashPw1 = crypto.createHmac('sha256', sessionID,).update(req.body.pw1).digest('hex');
  6. 조회한 Member1의 암호와 프론트에서 전달받아 hash한 암호(hashPw)가 동일한지 비교한다.
    : if (Member1.password === hashPw) { }
  7. 동일하면 Member1에 새 hashPw1을 넣어서 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});
    }
});

3. 회원탈퇴

  • 로그인 필요 = 토큰 검증
  1. 토큰 라이브러리 사용
    : const jwt = require('jsonwebtoken');
  2. /token/auth.js 사용
    : 변수명은 auth로 한다.
    : const auth = require('../token/auth');
  3. auth.checkToken
    : auth.js에서 module.exports한 메소드를 불러와서 사용한다.
    : 토큰 검증 후 복원해서 USERID와 USERNAME을 전달해주는 역할
  4. deleteOne의 조건(query)
    : const result = await Member.deleteOne(query);
    4-1. 아이디(토큰에서추출)
    : const sessionID = req.body.USERID;
    4-2. 암호(입력받은값을 HASH함)
    : 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});
    }
});
profile
The best

0개의 댓글