익명의 개발노트

[Wecode 29~30일차] Node JS로 API만들기 본문

코딩일기/TIL

[Wecode 29~30일차] Node JS로 API만들기

캡틴.JS 2019. 6. 30. 13:20
반응형

원래는 2주차 커리큘럼인데.. 몇명은 진도를 뛰어넘은 바람에 1주차때 미니트위터를 만들었고, 

3주차때 리액트로 기존에 만든 미니터를 다시 만들었다. 4주차에는 장고로 api를 구현하는 것이지만, 나는 프론트엔드 과정을 선택했

기에 따로 노드를 이용해서 로그인과 회원가입api를 만들었다.

1. 회원가입의 중요한 요소, 비밀번호 암호화

Node.JS의 암호화 모듈로는 여러가지가 있는데, 안전상 내장모듈은 crypto모듈을 이용했으며, pbkdf2버전의 업그레이드판인

pbkdf2Sync를 사용했다.

적용하기 전에 암호화에 대해서 살짝 알아보고 적용을 시켰다. 왜 사용하는지 모르고 사용하면 안되니깐.

app.post('/signup', (req,res)=>{
    console.log('signup post ok!');
    const body=req.body;  //body는 {} front 쪽에서 header에 content-type 지정을 해주어야 정상적으로 데이터 찍힌다.
    const user_id = body.user_id;
    const user_pw = body.user_pw;
    const user_name = body.user_name;
    const user_profile = body.profile;
    
    //암호화
    const key = crypto.pbkdf2Sync(user_pw, 'salt', 100000, 64, 'sha512').toString('hex');

    //escape 문법
    const sql ={user_id:user_id,user_pw:key, user_name:user_name,user_profile:user_profile};
    
    //id중복조회 후 없으면 삽입.
    const selectQuery = connection.query('select user_id from users where user_id=?',[user_id],(err,rows)=>{
        console.log(rows);
        if(rows.length == 0){
            const query = connection.query('insert into users set ?',sql,(err,rows)=>{
                if(err){
                    throw err;
                }else{
                    res.json({message : '200 OK'})   //프론트로 뿌려줌.
                }
            });
        }else{
            res.json({message : '400 Bad Request'}); 
        }
    });     
})

위 코드와 달리 처음에는 const key 부분을 아래와 같이 작성했다.

 const key = crypto.pbkdf2Sync(user_pw, 'salt', 100000, 64, 'sha512')

위의 문제점은 DB에 암호화되버서려 저장이 되는데.. 문제는 DB상에도 깨져서 저장이 된다.

단순 암호화 처리만 한 비밀번호 ...

이렇게 되면 문제점이 로그인 api작성할때, 로그인때 입력한 비밀번호와 매칭이 안된다는 점이다.

따라서, 암호화된 내용을 컴퓨터에 0,1로 저장할 필요가 있다. 16진수, 64진수 등등 방법이 여러개있는데,

64진수인 base64와 16진수인 hex(base16)를 놓고 고민을 하였다.

차이점이 뭔지 찾아본 결과 아래와 같은 결과를 얻어서 hex를 사용했다.

base64 has less overhead (base64 produces 4 characters for every 3 bytes of original data 
while hex produces 2 characters for every byte of original data). 
Hex is more readable - you just look at the two characters and immediately know what 
byte is behind,but with base64 you need effort decoding the 4-characters group, 
so debugging will be easier with hex.

결론은 hex를 사용하면 디버깅이 쉬워지고, 64진수를 이용하면 오버헤드는 적지만, 디코딩하는 노력이 필요하다.

진수를 사용하면 db에 이런식으로 저장이 된다.

진수로 바꾼 비밀번호

로그인은 회원가입과 비슷하다.

일단은 인증모듈인 passport가 있지만, passport없이 구현을 해보았다.

app.post('/login',(req,res)=>{
    const body=req.body; 
    const user_id = body.user_id;
    const user_pw = body.user_pw;   
  
    //id중복조회 
        const selectQuery = connection.query('select user_id,user_pw from users where user_id=?',[user_id],(err,rows)=>{
            if(err) throw err;
            
            if(!rows[0]){  
                console.log("클라이언트 전달")
                return res.json({message : 'not exist id',status: 500});
            }

             const key = crypto.pbkdf2Sync(user_pw, 'salt', 100000, 64, 'sha512').toString('hex');
             if(key === rows[0].user_pw){
                 return res.json({message : 'login success!', status : 200});
             }else{
                 return res.json({message : 'login failed!', status : 500});
             }       
        });    
})

아주 잘 작동한다.

로직은 쿼리의 콜백으로 rows가 배열에 객체 형식으로 값을 가져온다.

따라서, 쿼리에서 로그인한 id를 조회하고, 그결과가 rows에 들어오는데, rows[0]이나 rows가 없으면 아이디가 존재하지 않는 것이

고, 존재하면, 로그인한 비밀번호를 저장했던 진수방식과 동일하게 값을 주고 db에서 값을꺼내와 비교해야한다.

반응형
Comments