mongoDB + Postman + vue

국비 코딩 풀스택 수업 17일차

비루블 2022. 7. 14. 12:56

요약정리

오전(member.js , membermodel.js , auth.js)

모듈 설치

백엔드 작성(회원가입, 아이디중복확인, 로그인, 회원수정)

model의 중요성(모델이 바뀌면, 후에 만든 많은 코드들을 변경을 해야하는데 처음부터 잘 해놓는게 중요)

로그인(중요)은 post를 사용해야함(ps의 암호화 때문에.)

회원정보수정(중요) auth에서 함수를 끌어땡겨씀(토큰 확인 검증). member

원래라면 auth.js(개인정보 토큰부분)이 더욱 복잡하게 짜여져야함. 개인정보이기 때문에.

 


오전일과


회원가입 할거임
백엔드부터
모듈 깔아야함
CMD> npm i jsonwebtoken --save

memeber.js(진행중)

var express = require('express');
var router = express.Router();


// 문자를 hash 하기 위한 용도, 암호
const crypto = require('crypto')


// DB연동을 위한 모델 ORM
var Member = require('../models/membermodel');


// npm i moment
// npm i moment-timezone --save
require('moment-timezone');
var moment = require('moment');
moment.tz.setDefault('Asia/Seoul'); // 표준시 UTC 시간, 아시아.서울로 설정


//npm i jsonwebtoken --save
const jwt = require('jsonwebtoken');
// 외부에서 사용
const auth = require('../token/auth');


//회원정보 수정
//127.0.0.1:3000/member/update.json
// {"name":"변경1", "email":"b@b.com", "phone":"010-1111-1111"}
router.put('/update.json', auth.checkToken,  async function(req, res, next) {
    try{
        // 1. 전송값 받기
        const id = req.body.SID;
        const name =req.body.name;
        const email =req.body.email;
        const phone =req.body.phone;

        // 2. DB조건 설정
        const query = {_id : id};

        // 3. DB에서 정보 읽기
        const obj = await Member.findOne(query);
        obj.name = name;
        obj.email = email;
        obj.phone = phone;

        // 4. DB에 정보 변경
        const result = await obj.save();

        if(result !== null){
            return res.send({status:200})
        }

        return res.send({status:200, result:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});




// 로그인 =>
// 127.0.0.1:3000/member/login.json
// 토큰발행 : 접근토큰(9h), refresh토큰
// post 로그인은 post로 써야함. 암호때문에 post
// {"id":"aaaa", "pw":"bbbb"}
router.post('/login.json', async function(req, res, next) {
    try{
        // 1. 전달값 받기
        const id = req.body.id;
        const pw = req.body.pw;


        const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');

        // 2. Db검색을 위한 조건
        const query = {$and : [ { _id : id , password : hashPw}]}


        // 3. DB조회
        const result = await Member.findOne(query);
        

        // 4. 결과에 따른 리턴값 설정
        if(result !== null) { //조회했을때 일치하는게 있었다는 뜻
            // 여기에서 토큰 생성 (토큰에 포함할 정보, 보안키, 옵션)
            const token = jwt.sign({SID:id}, auth.securityKey, auth.options);

            return res.send({status:200, result:token});
        }
        

        return res.send({status:0});


    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});







// 아이디 중복확인
// 127.0.0.1:3000/member/idcheck.json?id=aaa
router.get('/idcheck.json', async function(req, res, next) {
    try{
        //1. wjsekfrkqt qkerl
        const id = req.query.id;

        //2. DB에 조회하는 조건
        const query = { _id : id };

        //3. DB에서 조회 수행
        const result = await Member.findOne(query);
        console.log(result);

        if(result !== null) {
            return res.send({status:200, result:1});
            //있을때
        }
        //없을때
        return res.send({status:200, result:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});







// 127.0.0.1:3000/member/insert.json
// { "id":"aaaa", "pw":"aaaa", "name":"가",
// "email":"a@a.com", "phone": "010-0000-0000"}으로옴
router.post('/insert.json', async function(req, res, next) {
    try{
        // 1. 전달값 받기
        const id = req.body.id;
        const pw = req.body.pw;
        const name = req.body.name;
        const email = req.body.email;
        const phone = req.body.phone;

        // 2. 암호정보 변경
        // A => aaaa => 123g34kk34fm5k3
        // B => aaaa => terkntk43mk5325
        const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');

        // 3. DB저장용 빈 객체 생성
        // membermodel.js를 참고해서 넣어줘야함
        const obj    = new Member();
        obj._id      = id;
        obj.password = hashPw;
        obj.name     = name;
        obj.email = email;
        obj.phone = phone;
        obj.regdate = moment().format('YYYY-MM-DD HH:mm:ss');

        // 4. DB에 저장하기
        const result = await obj.save();

        if(result !== null) {
            return res.send({status:200});
        }
        return res.send({status:0});


    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});

module.exports = router;

app.js 등록

var memberRouter = require('./routes/member');

app.use('/member', memberRouter);

 

 

모델스 membermodel.js작성(아이디 부여라 시퀀스 필요x)

// npm i mongoose --save
var mongoose = require('mongoose');

var Schema = mongoose.Schema;
var memberSchema =  new Schema({
    _id     : String, //아이디, 문자, 기본키, not null 비워두면 안되고, unique 고유해야한다.
    password: {type:String, default:''},//암호, 문자
    name    : {type:String, default:''}, //이름, 문자
    email   : {type:String, default:''},  //이메일, 문자
    phone :   {type:String, default:''}, //등록일, 현재시간으로 등록
    regdate : {type:String, default:''}
});

module.exports = mongoose.model('member', memberSchema);


_id에 고유값을 부여하기 때문에 같은 아이디로 생성시 오류가 뜸.
이전에 했던 게시글, 책게시글은 시퀀스넘버로 고유값을 부여했다면
여기서는 _id자체가 고유값이기 때문에 중복되면 에러가 뜸.

위 membermodel은 잘 작성해야함. 만약에 바꿀려고하면
후에 만들었던 코드 수정을 엄청 많이 해야함...


암호의 암호화
서버에 업로드할때 암호화됨
암호화된 코드에서 원래 비번으로 못돌아옴
그래서 사용자만 암호를 알 수 있음.
암호화(member.js > crypto(hash만들 것임.))
insert post 2번 참조
----------------------------------

insert post 작성

router.post('/insert.json', async function(req, res, next) {
    try{
        // 1. 전달값 받기
        const id = req.body.id;
        const pw = req.body.pw;
        const name = req.body.name;
        const email = req.body.email;
        const phone = req.body.phone;

        // 2. 암호정보 변경
        // A => aaaa => 123g34kk34fm5k3
        // B => aaaa => terkntk43mk5325
        const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');

        // 3. DB저장용 빈 객체 생성
        // membermodel.js를 참고해서 넣어줘야함
        const obj    = new Member();
        obj._id      = id;
        obj.password = hashPw;
        obj.name     = name;
        obj.email = email;
        obj.phone = phone;
        obj.regdate = moment().format('YYYY-MM-DD HH:mm:ss');

        // 4. DB에 저장하기
        const result = await obj.save();

        if(result !== null) {
            return res.send({status:200});
        }
        return res.send({status:0});


    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});


여기서 암호정보 변경을 함.
const hashPw = crypto.createHmac('sha256', salt값).update(pw);
sha256 일반적으로 많이쓰는 알고리즘
salt값 암호화할때 들어가는 키 값(같은 암호를 쓸때 암호화값도 같기 떄문에 더복잡하게 만들어줌)
(지금은 salt값에 id만 넣어줌. 이것도 간단한 편)

 


최종 완성

const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');

 

 

------------------------------------------------------------------------------------------
db에 업로드 할때 membermodel.js에 있는 변수들로 넣어줘야함
3. DB저장용 빈 객체 생성
// membermodel.js를 참고해서 넣어줘야함
const obj = new Member();
obj._id = id;
obj.password = hashPw;
obj.name = name;
obj.email = email;
obj.phone = phone;
obj.regdate = moment().format('YYYY-MM-DD HH:mm:ss');


obj는 membermodel.js를 참고해서 넣어줘야함.
-----------------------------------------------------------------------------------------

 

regdate쓸때 아래 코드 필요(member.js)

// npm i moment
// npm i moment-timezone --save
require('moment-timezone');
var moment = require('moment');
moment.tz.setDefault('Asia/Seoul'); // 표준시 UTC 시간, 아시아.서울로 설정

쓰는법

obj.regdate = moment().format('YYYY-MM-DD HH:mm:ss');




아이디 중복확인 (get idcheck.json)

// 아이디 중복확인
// 127.0.0.1:3000/member/idcheck.json?id=aaa
router.get('/idcheck.json', async function(req, res, next) {
    try{
        //1. wjsekfrkqt qkerl
        const id = req.query.id;

        //2. DB에 조회하는 조건
        const query = { _id : id };

        //3. DB에서 조회 수행
        const result = await Member.findOne(query);
        console.log(result);

        if(result !== null) {
            return res.send({status:200, result:1});
            //있을때
        }
        //없을때
        return res.send({status:200, result:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});

 

쿼리로 중복확인
아이디가 있으면 정보를 불러옴. 불러왔다는 뜻은 not null
그래서 status가 200으로 뜸. 그래서 result를 붙여주고 1,0으로 뜨게하고
중복확인 (result값이 1이면 중복, 0이면 없는 아이디)


 

post login.json

// 로그인 =>
// 127.0.0.1:3000/member/login.json
// 토큰발행 : 접근토큰(9h), refresh토큰
// post 로그인은 post로 써야함. 암호때문에 post
// {"id":"aaaa", "pw":"bbbb"}
router.post('/login.json', async function(req, res, next) {
    try{
        // 1. 전달값 받기
        const id = req.body.id;
        const pw = req.body.pw;


        const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');

        // 2. Db검색을 위한 조건
        const query = {$and : [ { _id : id , password : hashPw}]}


        // 3. DB조회
        const result = await Member.findOne(query);
        

        // 4. 결과에 따른 리턴값 설정
        if(result !== null) { //조회했을때 일치하는게 있었다는 뜻
            // 여기에서 토큰 생성 (토큰에 포함할 정보, 보안키, 옵션)
            const token = jwt.sign({SID:id}, auth.securityKey, auth.options);

            return res.send({status:200, result:token});
        }
        

        return res.send({status:0});


    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});


이제 로그인(토큰 이용할거임. 발급되는 시간부터 시작해서 )
중요중요중요중요중요중요중요중요중요중요중요중요중요중요중요
아이디, 암호를 기반으로 토큰을 발행 해줘야함.
토큰에는 access접근 토큰, refresh토근이 존재
일단 우리는 접근토큰, refresh는 시간 정해주는 로그인임.
접근토큰으로 10시간만 할것임.

 


로그인은 따로 관리해야해서 폴더를 따로 만들음.
exp_20220711>token>auth.js(토큰 발행용 정보 설정, 토큰 검증)
npm i jsonwebtoken --save

// 파일명 : token/auth.js

//npm i jsonwebtoken --save
const jwt = require('jsonwebtoken');


// 토큰발행용 정보 설정
// 토큰검증
const auth = {
    securityKey : 'asdfasdfasdfsadfasdfwe23123sdf', // 토큰발행시 salt 값

    options : {
        algorithm : 'HS256', // 토큰 생성 알고리즘 종류
        expiresIn : '10h',   // 토큰 유효 시간 10시간, 30분 하려면 30m
        issuer    : 'ds corp'// 발행자
    },
    checkToken : async(req, res, next) => { // 토큰 검증
        try{
        const token = req.headers.token;

        if(typeof token === 'undefined'){
            return res.send({status:0, result:'토큰없음'})
        }

        if(token === ''){
            return res.send({status:0, result:'토큰없음'})
        }

        //토큰 내용 복원 ( 토큰, 보안키 )
        // { SID: 'aaaa', iat: 1657763361, exp: 1657799361, iss: 'ds corp' }
        const data = jwt.verify( token, auth.securityKey );
        console.log(data);

        //member.js에서 아이디를 꺼내기 위해서 req.body에 저장함.
        req.body.SID = data.SID;
        
        next(); // 다음의 주소로 전달되는 것.(현재는 memeber.js로 이동)
        }
        catch(e){
            console.error(e);
            return res.send({status:0, result:'토큰 오류'})
        }
    }

};

module.exports = auth; // 이렇게 해줘야 외부에서 사용가능. 폴더가 다름.

 

시큐리티키(토큰발행시 salt값)
알고리즘HS256
얼마나 10h
발행자 ds corp


-------------------------------------------
다시 member.js에 돌아와서 로그인 작업
member.js에 추가(auth.js를 member.js에서 사용가능)

const auth = require('../token/auth');
//npm i jsonwebtoken --save
const jwt = require('jsonwebtoken');

 

위 꺼는 로그인시 리턴에 토큰 줄때 사용
아래꺼는 암호화 관련

// post 로그인은 post로 써야함. 암호때문에 post

db검색을 위한 조건 query

const query = {$and : [ { _id : id , password : hashPw}]}



해쉬 추가(암호화해서 보내서 확인)

const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');


결과에 따른 리턴값 설정(조회했을 때 일치하는게 있었다는 뜻)
토큰생성 해줘야 함.

if(result !== null) { //조회했을때 일치하는게 있었다는 뜻
    // 여기에서 토큰 생성 (토큰에 포함할 정보, 보안키, 옵션)
    const token = jwt.sign({SID:id}, auth.securityKey, auth.options);

    return res.send({status:200, result:token});
}

결과가 존재 한다면, token에 정보를 넣음.



회원정보 수정 put update.json

//회원정보 수정
//127.0.0.1:3000/member/update.json
// {"name":"변경1", "email":"b@b.com", "phone":"010-1111-1111"}
router.put('/update.json', auth.checkToken,  async function(req, res, next) {
    try{
        // 1. 전송값 받기
        const id = req.body.SID;
        const name =req.body.name;
        const email =req.body.email;
        const phone =req.body.phone;

        // 2. DB조건 설정
        const query = {_id : id};

        // 3. DB에서 정보 읽기
        const obj = await Member.findOne(query);
        obj.name = name;
        obj.email = email;
        obj.phone = phone;

        // 4. DB에 정보 변경
        const result = await obj.save();

        if(result !== null){
            return res.send({status:200})
        }

        return res.send({status:200, result:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});


아이디가 토큰에 안담겨 있어서 아직 못함
토큰 검증하고 진행


auth.js로 가서 토큰 검증
checkToken
token을 headers로 받기 때문에 postman에서 headers로 줌

Headers에 토큰, body raw json에 정보를 기입해야 회원 정보가 수정이 됨.

 


token유효성 확인

    checkToken : async(req, res, next) => { // 토큰 검증
        try{
        const token = req.headers.token;

        if(typeof token === 'undefined'){
            return res.send({status:0, result:'토큰없음'})
        }

        if(token === ''){
            return res.send({status:0, result:'토큰없음'})
        }

 


------
회원정보 수정에
checkToken 함수를 넣음.(토큰이 명확해야하는 페이지)
함수가 먼저 실행됨.

router.put('/update.json', auth.checkToken,  async function(req, res, next)

 

checkToken을 먼저 넣고 async 펑션을 넣었기 떄문에
checkToken이 먼저 실행됨.
------

다시 auth로 와서
checkToken
유효성 검사(if)

    checkToken : async(req, res, next) => { // 토큰 검증
        try{
        const token = req.headers.token;

        if(typeof token === 'undefined'){
            return res.send({status:0, result:'토큰없음'})
        }

        if(token === ''){
            return res.send({status:0, result:'토큰없음'})
        }



토큰 내용복원( 토큰, 보안키 ) 중요중요중요중요중요중요중요중요

        const data = jwt.verify( token, auth.securityKey );
        console.log(data);

위코드 사용시
{ SID: 'aaaa', iat: 1657763361, exp: 1657799361, iss: 'ds corp' }
정상적인 토큰이라면 이렇게 뜸.(백엔드 cmd)

 


const data = jwt.verify( token, auth.securityKey );
이게 오류가 발생하면(토큰키가 맞지 않을때)
catch(e)로 바로 넘어감.next()까지 가지 않아서 다음 페이지에 정보를 안넘겨준다는 말.

(원래는 catch(e)에서 오류 세분화를 해야함 그러나 생략)
기회가 된다면 오류 세분화를 해주신다 함.


원래라면
이게 원래 엄청 더 복잡해야함.
개인 정보이기 떄문에 더욱 더 까다롭게 만들어야함.

 

회원정보 수정 다시 돌아와서
정보변경에 복원된 아이디를 넘겨야하는데 방법이 없음.
그래서 수동으로 심어줌
req.body.SID = data.SID;


member.js > put update.json
토큰이 헤더스에 제대로 입력되어 있고,
body raw json에 제대로 정보가 기입 되면 정보 변경이 됨.

해당글 회원정보 수정 처음 시작하는 부분에 postman 사진으로 설명 해놓음.


 

=======================================

 

오후 일과

회원 탈퇴

//회원탈퇴
//127.0.0.1:3000/member/delete.json
//{"pw": ""}
router.delete('/delete.json', auth.checkToken,  async function(req, res, next) {
    try{

        // 1. 전달값 받기
        const id =req.body.SID;
        const pw =req.body.pw;


        // 2. 삭제 조건 만들기
        const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');
        const query = {$and : [ { _id : id , password : hashPw}]};

        // 3. DB에 삭제
        const result = await Member.deleteOne(query);

        // 4. 결과에 따라 반환값 설정
        if(result.deletedCount === 1){
            return res.send({status:200});
        }
        return res.send({status:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});

 



암호변경

//암호 변경
// 127.0.0.1:3000/memeber/updatepw.json
// {pw:"aaaa", "pw1":"bbbb"}
router.put('/updatepw.json', auth.checkToken,  async function(req, res, next) {
    try{
        // 1. 전송값 받기
        const id = req.body.SID;
        const pw = req.body.pw;
        const pw1 = req.body.pw1;

        // 2. DB조건 설정
        const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');
        const query = {$and : [ { _id : id , password : hashPw}]};

        // 3. DB에서 정보 읽기
        const obj = await Member.findOne(query);


        if(obj !== null){
            //변경암호
            const hashPw1 = crypto.createHmac('sha256', id).update(pw1).digest('hex');
            obj.password = hashPw1;
            const result = await obj.save();
            if(result !== null){
                return res.send({status:200})
            }
        }



        return res.send({status:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});

 

jwt를 auth.js에 generateToken로 옮김(함수를 옮겨서)

수정된 

generateToken : (data) => {
    const token = jwt.sign(data, auth.securityKey, auth.options);
    return token;
},



로그인에서
jwt를 빼고 로그인시 result값에 바로 토큰을 주도록 변경

return res.send({status:200, result:auth.generateToken({SID:id})});




뷰로  ui  만들것임.

app.vue 추가

<template>
  <div>
    <router-link to="/login"><button>로그인</button></router-link>
    <router-link to="/join"><button>회원가입</button></router-link>
    <router-link to="/logout"><button>로그아웃</button></router-link>
    <router-link to="/mypage"><button>마이페이지</button></router-link>

    <router-view></router-view>
    
  </div>
</template>


아이디 중복확인, 유효성 검사

회원가입 만듬.(레퍼런스 focus)

<template>
    <div class="container">
        {{state}}
        <h3>회원가입</h3>
        <div>
            <label class="lbl">아이디</label>
            <input type="text" v-model="state.id" @keyup="handleIDCheck" ref="id"/>
            <label v-html="state.idcheck"></label>
        </div>
        <div>
            <label class="lbl">암호</label>
            <input type="password" v-model="state.pw" ref="pw"/>
        </div>
        <div>
            <label class="lbl">암호확인</label>
            <input type="password" v-model="state.pw1" ref="pw1"/>
        </div>
        <div>
            <label class="lbl">이름</label>
            <input type="text" v-model="state.name" ref="name"/>
        </div>
        <div>
            <label class="lbl">이메일</label>
            <input type="text" v-model="state.email1"/>
            <label>@</label>
            <select v-model="state.email2">
                <option>naver.com</option>
                <option>daum.net</option>
                <option>gmail.com</option>
            </select>
        </div>
        <div>
            <label class="lbl">연락처</label>
            <input type="text" style="width:50px" v-model="state.phone1" />
            <label>-</label>
            <input type="text" style="width:50px" v-model="state.phone2" />
            <label>-</label>
            <input type="text" style="width:50px" v-model="state.phone3" />
        </div>
        <div style="margin-top:10px">
            <label class="lbl"></label>
            <button @click="handleJoin">회원가입</button>
        </div>
    </div>
</template>

<script>
import { reactive, ref } from '@vue/reactivity'
import axios from 'axios';
export default {
    setup () {

        const id = ref();
        const pw = ref();
        const pw1 = ref();
        const name = ref();

        // onMounted(()=>{
        //     id.value.focus();
        // });

        const state = reactive({
            id      : '',
            pw      : '',
            pw1     : '',
            name    : '',
            email1  : '',
            email2  : 'daum.net',
            phone1  : '',
            phone2  : '',
            phone3  : '',
            idcheck : '중복확인',
        });


        const handleIDCheck = async() => {
            if ( state.id.length > 3 ){
                const url = `/member/idcheck.json?id=${state.id}`;
                const headers = {"Content-Type":"application/json"};
                const {data} = await axios.get(url, {headers})
                console.log(data);
                if(data.status === 200) {
                    if(data.result === 1){
                        state.idcheck = `<font color="red">사용불가</font>`
                    }
                    if(data.result === 0){
                        state.idcheck = `<font color="green">사용가능</font>`
                    }
                }
                else{state.idcheck = '중복확인';}
            }
            else{state.idcheck = '중복확인';}
        };

        const handleJoin = async() => {
            //유효성 검사
            if(state.id === ''){
                alert('아이디를 입력하세요.')
                id.value.focus();
                return false;
            }
            if(state.pw === ''){
                alert('암호를 입력하세요.')
                pw.value.focus();
                return false;
            }
            if(state.pw1 === ''){
                alert('암호확인을 입력하세요.')
                pw1.value.focus();
                return false;
            }
            if(state.name === ''){
                alert('이름을 입력하세요.')
                name.value.focus();
                return false;
            }


            const url = `/member/insert.json`;
            const headers = {"Content-Type":"application/json"};
            const body = {
                id : state.id,
                pw : state.pw,
                name : state.name,
                email : state.email1 + '@' + state.email2,
                phone : state.phone1 + '-' + state.phone2 + '-' + state.phone3
            };
            console.log(body);
            const {data} = await axios.post(url, body,{headers});
            console.log(data);
            if(data.status === 200){
                alert('회원가입 완료')
                // router.push({path:'/'})
            }
        }

        return {
            id,
            pw,
            pw1,
            name,
            state, 
            handleIDCheck,
            handleJoin
        };
    }
}
</script>

<style lang="css" scoped>
    .container {
        width:500px;
        border: 1px solid #cccccc;
        padding:20px;
    }

    .lbl {
        display: inline-block;
        width:90px;
    }
</style>

 



새로 바뀐 auth.js 와 member.js

auth.js


// 파일명 : token/auth.js

//npm i jsonwebtoken --save
const jwt = require('jsonwebtoken');


// 토큰발행용 정보 설정
// 토큰검증
const auth = {
    securityKey : 'asdfasdfasdfsadfasdfwe23123sdf', // 토큰발행시 salt 값

    options : {
        algorithm : 'HS256', // 토큰 생성 알고리즘 종류
        expiresIn : '10h',   // 토큰 유효 시간 10시간, 30분 하려면 30m
        issuer    : 'ds corp'// 발행자
    },

    generateToken : (data) => {
        const token = jwt.sign(data, auth.securityKey, auth.options);
        return token;
    },

    checkToken : async(req, res, next) => { // 토큰 검증
        try{
        const token = req.headers.token;

        if(typeof token === 'undefined'){
            return res.send({status:0, result:'토큰없음'})
        }

        if(token === ''){
            return res.send({status:0, result:'토큰없음'})
        }

        //토큰 내용 복원 ( 토큰, 보안키 )
        // { SID: 'aaaa', iat: 1657763361, exp: 1657799361, iss: 'ds corp' }
        const data = jwt.verify( token, auth.securityKey );
        console.log(data);

        //member.js에서 아이디를 꺼내기 위해서 req.body에 저장함.
        req.body.SID = data.SID;
        
        next(); // 다음의 주소로 전달되는 것.(현재는 memeber.js로 이동)
        }
        catch(e){
            console.error(e);
            return res.send({status:0, result:'토큰 오류'})
        }
    }

};

module.exports = auth; // 이렇게 해줘야 외부에서 사용가능. 폴더가 다름.

member.js

var express = require('express');
var router = express.Router();


// 문자를 hash 하기 위한 용도, 암호
const crypto = require('crypto')


// DB연동을 위한 모델 ORM
var Member = require('../models/membermodel');


// npm i moment
// npm i moment-timezone --save
require('moment-timezone');
var moment = require('moment');
moment.tz.setDefault('Asia/Seoul'); // 표준시 UTC 시간, 아시아.서울로 설정


// 외부에서 사용
const auth = require('../token/auth');


//암호 변경
// 127.0.0.1:3000/memeber/updatepw.json
// {pw:"aaaa", "pw1":"bbbb"}
router.put('/updatepw.json', auth.checkToken,  async function(req, res, next) {
    try{
        // 1. 전송값 받기
        const id = req.body.SID;
        const pw = req.body.pw;
        const pw1 = req.body.pw1;

        // 2. DB조건 설정
        const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');
        const query = {$and : [ { _id : id , password : hashPw}]};

        // 3. DB에서 정보 읽기
        const obj = await Member.findOne(query);


        if(obj !== null){
            //변경암호
            const hashPw1 = crypto.createHmac('sha256', id).update(pw1).digest('hex');
            obj.password = hashPw1;
            const result = await obj.save();
            if(result !== null){
                return res.send({status:200})
            }
        }



        return res.send({status:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});







//회원탈퇴
//127.0.0.1:3000/member/delete.json
//{"pw": ""}
router.delete('/delete.json', auth.checkToken,  async function(req, res, next) {
    try{

        // 1. 전달값 받기
        const id =req.body.SID;
        const pw =req.body.pw;


        // 2. 삭제 조건 만들기
        const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');
        const query = {$and : [ { _id : id , password : hashPw}]};

        // 3. DB에 삭제
        const result = await Member.deleteOne(query);

        // 4. 결과에 따라 반환값 설정
        if(result.deletedCount === 1){
            return res.send({status:200});
        }
        return res.send({status:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});







//회원정보 수정
//127.0.0.1:3000/member/update.json
// {"name":"변경1", "email":"b@b.com", "phone":"010-1111-1111"}
router.put('/update.json', auth.checkToken,  async function(req, res, next) {
    try{
        // 1. 전송값 받기
        const id = req.body.SID;
        const name =req.body.name;
        const email =req.body.email;
        const phone =req.body.phone;

        // 2. DB조건 설정
        const query = {_id : id};

        // 3. DB에서 정보 읽기
        const obj = await Member.findOne(query);
        obj.name = name;
        obj.email = email;
        obj.phone = phone;

        // 4. DB에 정보 변경
        const result = await obj.save();

        if(result !== null){
            return res.send({status:200})
        }

        return res.send({status:200, result:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});




// 로그인 =>
// 127.0.0.1:3000/member/login.json
// 토큰발행 : 접근토큰(9h), refresh토큰
// post 로그인은 post로 써야함. 암호때문에 post
// {"id":"aaaa", "pw":"bbbb"}
router.post('/login.json', async function(req, res, next) {
    try{
        // 1. 전달값 받기
        const id = req.body.id;
        const pw = req.body.pw;


        const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');

        // 2. Db검색을 위한 조건
        const query = {$and : [ { _id : id , password : hashPw}]}


        // 3. DB조회
        const result = await Member.findOne(query);
        

        // 4. 결과에 따른 리턴값 설정
        if(result !== null) { //조회했을때 일치하는게 있었다는 뜻
            // 여기에서 토큰 생성 (토큰에 포함할 정보, 보안키, 옵션)
            return res.send({status:200, result:auth.generateToken({SID:id})});
        }
        

        return res.send({status:0});


    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});







// 아이디 중복확인
// 127.0.0.1:3000/member/idcheck.json?id=aaa
router.get('/idcheck.json', async function(req, res, next) {
    try{
        //1. wjsekfrkqt qkerl
        const id = req.query.id;

        //2. DB에 조회하는 조건
        const query = { _id : id };

        //3. DB에서 조회 수행
        const result = await Member.findOne(query);
        console.log(result);

        if(result !== null) {
            return res.send({status:200, result:1});
            //있을때
        }
        //없을때
        return res.send({status:200, result:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});







// 127.0.0.1:3000/member/insert.json
// { "id":"aaaa", "pw":"aaaa", "name":"가",
// "email":"a@a.com", "phone": "010-0000-0000"}으로옴
router.post('/insert.json', async function(req, res, next) {
    try{
        // 1. 전달값 받기
        const id = req.body.id;
        const pw = req.body.pw;
        const name = req.body.name;
        const email = req.body.email;
        const phone = req.body.phone;

        // 2. 암호정보 변경
        // A => aaaa => 123g34kk34fm5k3
        // B => aaaa => terkntk43mk5325
        const hashPw = crypto.createHmac('sha256', id).update(pw).digest('hex');

        // 3. DB저장용 빈 객체 생성
        // membermodel.js를 참고해서 넣어줘야함
        const obj    = new Member();
        obj._id      = id;
        obj.password = hashPw;
        obj.name     = name;
        obj.email = email;
        obj.phone = phone;
        obj.regdate = moment().format('YYYY-MM-DD HH:mm:ss');

        // 4. DB에 저장하기
        const result = await obj.save();

        if(result !== null) {
            return res.send({status:200});
        }
        return res.send({status:0});


    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});

module.exports = router;