간단한 로그인 / 회원가입 #2

jh_leitmotif·2021년 6월 17일
0

🧐 Login & Register

로그인과 회원가입 기능은 어떤 웹 서비스든 빠지지 않는 기본 기능입니다.

쿼리를 통해 DB에 저장된 정보와 매칭되는지 확인하고, 각 서비스를 진행합니다.

📋 Table 구조

코드를 살펴보기 전, 아래는 미리 제가 만든 테이블입니다.

여기에 표시는 안되어있지만 ( ID, PW, UNAME )은 NOT NULL이 걸려있습니다.

향후 쓰일 서비스에 따라 다른 column들 또한 NOT NULL을 걸 수도 있겠습니다.

현재 들어가 있는 데이터들입니다.

📂 Login

로그인을 위한 기능입니다.

📄 테스트용 HTML 페이지

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JOIN</title>
</head>
    <body>
    <h1>Login Page </h1>
    <form action="/login" method="post">
        id : <input type="text" name="id"><br>
        password : <input type="password" name="pw"><br>
        <input type="submit">
    </form>

    </body>
</html>

잠깐 주시해야되는 것은 method="post" 였습니다.

🎯 GET VS POST

사전적으로는 받아오다 / 게시하다 로, 문자 그대로의 역할을 맡습니다.

GET : 서버의 리소스에서 데이터를 요청할 때 사용된다.

POST : 서버의 리소스를 새로 생성하거나 업데이트할 때 사용한다

따라서 GET은 반복적인 작업에, POST는 일회적인 것에 자주 쓰일 것입니다.

여기서 주목한 것은 GET이 정보를 URL에 노출한다는 것입니다.

예를 들어 GET방식을 사용했다면,

URL : 127.0.0.1:5000/id=~pw~

이런 방식으로 되어 정보 노출을 피할 수 없습니다.

그러므로 따라서 Login과 Register 모두 POST 방식을 사용했습니다.

물론 비밀번호를 SHA 암호화한다거나...하는 깊이있는 보안이 있기 때문에

최소한의 장치라는 느낌입니다.

📄 userLogin.js

다시 돌아와, javascript 코드를 보겠습니다.

const router = require('express').Router();
const path = require('path');


router.post('/login',(req,res)=>{
    const mysql = require('../database')();
    const connection = mysql.init();
    mysql.db_open(connection);
    const userid = req.body.id;
    const userpw = req.body.pw;
    connection.query('SELECT * FROM USERS WHERE id = ? AND pw = ? ',[userid, userpw], (err, results, fields) =>{
        if (err){
            throw err;
        }else if (results.length>0){
            res.send('<script type="text/javascript">alert("환영합니다!");</script>');
        }else{
            res.send('<script>alert("로그인 정보가 일치하지 않습니다."); document.location.href="/login";</script>');
        }
        connection.end(); // DB 연결 끊기
    });
    
})


module.exports = router;

이전 POST에서처럼 라우팅 분리를 진행했습니다.

로그인에 성공하면 '환영합니다' 팝업이 발생합니다.
만약 정보가 맞지 않다면 오류 팝업을 발생시킨 뒤 다시 Login 페이지로 돌아갑니다.

딱히 특이사항이랄 것은 없고, DB 연동 부분의 위치를 손보았습니다.

기존엔 서버를 실행하면 즉시 연결되는 구조였으나,

로그인 버튼을 눌렀을 때 연결하여 작업을 진행한 뒤 그것이 성공이든 실패이든 연결해제 [ connection.end(); ] 하여 자원을 반환시켰습니다.

여기에서 보완할 것은 당연히 Password 암호화일 것입니다.

현 단계에서는 기본 틀 짜기이기 때문에 쓰지 않았습니다.

📂 Register

회원가입을 위한 기능입니다.

📄 테스트용 HTML 페이지

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JOIN</title>
</head>
    <body>
    <h1>Join my website! </h1>
    <form action="/register" method="post">
        id : <input type="text" name="id"><br>
        password : <input type="password" name="pw"><br>
        password2 : <input type="password" name="pw2"><br>
        username : <input type="text" name="uname"><br>
        <input type="submit">
    </form>

    </body>
</html>

위에 올린 것과 같이 여러가지 COLUMN은 있으나 필수인 것만 넣었습니다.

📄 userRegister.js

const router = require('express').Router();
const path = require('path');


router.post('/register',(req,res)=>{
    const mysql = require('../database')();
    const connection = mysql.init();
    mysql.db_open(connection);
    const userid = req.body.id;
    const userpw = req.body.pw;
    const userpw2 = req.body.pw2;
    const username = req.body.uname;
    if (userid && userpw && userpw2 && username){
        connection.query('SELECT * FROM USERS WHERE id = ? OR uname = ?',[userid,username], (err, results, fields) =>{
            if (err){
                throw err;
            }else if (results.length<=0 && userpw == userpw2){
                connection.query('INSERT INTO USERS (id, pw, uname) VALUES(?,?,?)',[userid,userpw,username], (err,data)=>{
                    if (err){
                        console.log(err);
                    }
                });
                res.send(`<script type="text/javascript">alert("${username}님 환영합니다!"); document.location.href="/";</script>`);
            }else if (userpw!=userpw2){
                res.send(`<script type="text/javascript">alert("비밀번호가 다릅니다."); document.location.href="/register";</script>`);
            }
            else if (userid==results[0].ID){
                res.send('<script type="text/javascript">alert("이미 존재하는 아이디입니다."); document.location.href="/register";</script>');
            }else if (username==results[0].UNAME){
                res.send('<script type="text/javascript">alert("이미 존재하는 닉네임입니다."); document.location.href="/register";</script>');
            }else{
                res.send('<script type="text/javascript">alert("이미 존재하는 유저입니다."); document.location.href="/register";</script>');
            }
            connection.end();
        });
    }else{
        res.send('<script type="text/javascript">alert("정보를 모두 입력해주세요."); document.location.href="/register";</script>');
        connection.end();
    }   
})


module.exports = router;

userLogin.js와 크게 다를바 없습니다만 체크해야할 것이 좀 많습니다.

Checklist

  • 모든 정보가 입력되었는가?
  • DB에 없는 정보인가?
    - 중복되는 ID인가?
    - 중복되는 닉네임인가?

connection.query의 callback 함수에서 results는 쿼리구문의 결과를 뜻합니다.

이 때 results는 다음과 같은 배열 방식으로 확인됩니다.

따라서 results.length<=0 라면 DB에 일치하는 정보가 없는 것입니다.

또한 입력한 password가 2차 password와 동일해야 INSERT 쿼리가 작동합니다.

더불어 ID 또는 UNAME은 중복되지 말아야하고 어떤 항목이 중복인지 알려주기 위해 else if로 분기했습니다.

앞서 results는 배열 방식으로 표기되므로,

results[0].ID==userid
results[0].UNAME==username

과 같이 값을 js로 꺼내와 비교할 수 있습니다.


다음 예정된 작업은 암호화 및 세션입니다.

위에 작성된 것은 예제일 뿐,
실제 적용된다면 개인정보가 빠져나가기 딱 좋을 것입니다.

개발자조차 사용자의 PW를 알 수 없도록 DB엔 해싱된 값이 저장되어야하며
비밀번호 찾기와 같은 기능은 비밀번호를 새로 설정하도록 유도해야합니다.

즉 테이블 구조 변경 및 로그인/회원가입의 쿼리문 변경이 필요합니다.

사용할 해싱 함수는 SHA-256입니다.

세션은 중첩 로그인 방지 및 로그아웃 기능 구현을 위해 진행할 것입니다.

profile
Define the undefined.

0개의 댓글