본문 바로가기
프로그래밍 개발/Express

Express - 쿠키를 이용한 인증 기능 구현하기

by Jinseok Kim 2021. 1. 15.
반응형

 

 

쿠키를 이용한 인증 기능 구현하기

 

 

 

main.js

var http = require('http');
var fs = require('fs');
var url = require('url');
var qs = require('querystring');
var template = require('./lib/template.js');
var path = require('path');
var sanitizeHtml = require('sanitize-html');
var cookie = require('cookie'); //쿠키를 사용하기 위한 추가

//올바른 쿠키 데이터이 들어오면 isOwner가 false에서 true가 되도록 하는 함수 따로 만듬.
function authIsOwner(request, response){
    var isOwner = false;
    var cookies = {}
    if(request.headers.cookie){
        cookies = cookie.parse(request.headers.cookie);
    }
    if (cookies.email === 'k0502s@naver.com' && cookies.password === '061599'){
        isOwner = true;
    }
    return isOwner;
}

//함수 authIsOwner가 true(isOwner = true)로 호출되면 login UI가 logout으로 바뀌게 하였음.
// 또한 logout a링크 클릭시 실행되는 경로 또한 logout_process으로 전환시켜줌.
function authStatusUI(request, response){
    var authStatusUI = '<a href="/login">login</a>';
    if (authIsOwner(request, response)){
        authStatusUI = '<a href="/logout_process">logout</a>';
    }
    return authStatusUI;
}


var app = http.createServer(function(request,response){
    var _url = request.url;
    var queryData = url.parse(_url, true).query;
    var pathname = url.parse(_url, true).pathname;
    if(pathname === '/'){
      if(queryData.id === undefined){
        fs.readdir('./data', function(error, filelist){
          var title = 'Welcome';
          var description = 'Hello, Node.js';
          var list = template.list(filelist);
          var html = template.HTML(title, list,
            `<h2>${title}</h2>${description}`,
            `<a href="/create">create</a>`,
            authStatusUI(request, response) //login, logout 상황 별 전환                      
          );
          response.writeHead(200);
          response.end(html);
        });
      } else {
        fs.readdir('./data', function(error, filelist){
          var filteredId = path.parse(queryData.id).base;
          fs.readFile(`data/${filteredId}`, 'utf8', function(err, description){
            var title = queryData.id;
            var sanitizedTitle = sanitizeHtml(title);
            var sanitizedDescription = sanitizeHtml(description, {
              allowedTags:['h1']
            });
            var list = template.list(filelist);
            var html = template.HTML(sanitizedTitle, list,
              `<h2>${sanitizedTitle}</h2>${sanitizedDescription}`,
              ` <a href="/create">create</a>
                <a href="/update?id=${sanitizedTitle}">update</a>
                <form action="delete_process" method="post">
                  <input type="hidden" name="id" value="${sanitizedTitle}">
                  <input type="submit" value="delete">
                </form>` , authStatusUI(request, response) //login, logout 상황 별 전환
            );
            response.writeHead(200);
            response.end(html);
          });
        });
      }
    } else if(pathname === '/create'){
    //만약 authIsOwner(request, response)가 로그인 할 수 있는 쿠키 값이 틀려 false라면
    // create 모드가 실행되지 않도록 설정하였음. 다른 update, delete 등등 모두 적용함.
         if(authIsOwner(request, response) === false){
      response.end('Login required!!');
      return false;
    }
      fs.readdir('./data', function(error, filelist){
        var title = 'WEB - create';
        var list = template.list(filelist);
        var html = template.HTML(title, list, `
          <form action="/create_process" method="post">
            <p><input type="text" name="title" placeholder="title"></p>
            <p>
              <textarea name="description" placeholder="description"></textarea>
            </p>
            <p>
              <input type="submit">
            </p>
          </form>
        `, '', authStatusUI(request, response)); //login, logout 상황 별 전환
        response.writeHead(200);
        response.end(html);
      });
    } else if(pathname === '/create_process'){
         if(authIsOwner(request, response) === false){
      response.end('Login required!!');
      return false;
    }
      var body = '';
      request.on('data', function(data){
          body = body + data;
      });
      request.on('end', function(){
          var post = qs.parse(body);
          var title = post.title;
          var description = post.description;
          fs.writeFile(`data/${title}`, description, 'utf8', function(err){
            response.writeHead(302, {Location: `/?id=${title}`});
            response.end();
          })
      });
    } else if(pathname === '/update'){
         if(authIsOwner(request, response) === false){
      response.end('Login required!!');
      return false;
    }
      fs.readdir('./data', function(error, filelist){
        var filteredId = path.parse(queryData.id).base;
        fs.readFile(`data/${filteredId}`, 'utf8', function(err, description){
          var title = queryData.id;
          var list = template.list(filelist);
          var html = template.HTML(title, list,
            `
            <form action="/update_process" method="post">
              <input type="hidden" name="id" value="${title}">
              <p><input type="text" name="title" placeholder="title" value="${title}"></p>
              <p>
                <textarea name="description" placeholder="description">${description}</textarea>
              </p>
              <p>
                <input type="submit">
              </p>
            </form>
            `,
            `<a href="/create">create</a> <a href="/update?id=${title}">update</a>`,
            authStatusUI(request, response) //login, logout 상황 별 전환
          );
          response.writeHead(200);
          response.end(html);
        });
      });
    } else if(pathname === '/update_process'){
         if(authIsOwner(request, response) === false){
      response.end('Login required!!');
      return false;
    }
      var body = '';
      request.on('data', function(data){
          body = body + data;
      });
      request.on('end', function(){
          var post = qs.parse(body);
          var id = post.id;
          var title = post.title;
          var description = post.description;
          fs.rename(`data/${id}`, `data/${title}`, function(error){
            fs.writeFile(`data/${title}`, description, 'utf8', function(err){
              response.writeHead(302, {Location: `/?id=${title}`});
              response.end();
            })
          });
      });
    } else if(pathname === '/delete_process'){
         if(authIsOwner(request, response) === false){
      response.end('Login required!!');
      return false;
    }
      var body = '';
      request.on('data', function(data){
          body = body + data;
      });
      request.on('end', function(){
          var post = qs.parse(body);
          var id = post.id;
          var filteredId = path.parse(id).base;
          fs.unlink(`data/${filteredId}`, function(error){
            response.writeHead(302, {Location: `/`});
            response.end();
          })
      });
      // 경로 /login이 호출되면 아래 코드들이 실행되도록 하였음.
      // 로그인 할 수 있는 쿠키값을 입력할 수 있도록 폼 태크 설정함.
    } else if(pathname === '/login'){
      fs.readdir('./data', function(error, filelist){
        var title = 'Login';
        var list = template.list(filelist);
        var html = template.HTML(title, list, `
          <form action="/login_process" method="post">
            <p><input type="text" name="email" placeholder="email"></p>
            <p>
            <p><input type="password" name="password" placeholder="password"></p>
            <p>
              <input type="submit">
            </p>
          </form>
        `, `<a href="/create">create</a>`);
        response.writeHead(200);
        response.end(html);
      });
      
      //위에 로그인 폼에서 받은 로그인 정보 값들을 여기서 받아 쿠키 데이터로서 바꿔줌.
    } else if(pathname === '/login_process'){
      var body = '';
      request.on('data', function(data){
          body = body + data;
      });
      request.on('end', function(){
          var post = qs.parse(body);
          if(post.email === 'k0502s@naver.com' && post.password === '061599'){
            response.writeHead(302, 
             {'set-Cookie':[
               `email=${post.email}`,
            `password=${post.password}`,
             `nickname=jinseok`],                 Location: `/`});
                response.end();
        //받은 로그인 값 정보가 틀리면 who?라고 오류 메세지 전달해줌.        
      } else {
        response.end('Who?');
      }
      });
      
      //logout을 하면 받고 있었던 로그인 쿠키 값들을 모두 초기화 시키고 초기화면으로 돌아가게함.
    } else if (pathname === '/logout_process'){
         if(authIsOwner(request, response) === false){
      response.end('Login required!!');
      return false;
    }
    var body = '';
    request.on('data', function (data) {
      body = body + data;
    });
    request.on('end', function () {
      var post = qs.parse(body);
      response.writeHead(302, {
      //쿠키 값들 Max-Age을 사용하여 유효시간 0으로 만들어버림.
        'Set-Cookie': [
          `email=; Max-Age=0`,
          `password=; Max-Age=0`,
          `nickname=; Max-Age=0`
        ],
        Location: `/`
      });
      response.end();
    }); 
    } else {
      response.writeHead(404);
      response.end('Not found');
    }
});
app.listen(3000);

 

template.js

module.exports = {                          //이와 같이 login UI을 추가해줌.
  HTML:function(title, list, body, control, authStatusUI = '<a href="/login">login</a>'){
    return `
    <!doctype html>
    <html>
    <head>
      <title>WEB1 - ${title}</title>
      <meta charset="utf-8">
    </head>
    <body>
      ${authStatusUI} //추가
      <h1><a href="/">WEB</a></h1>
      ${list}
      ${control}
      ${body}
    </body>
    </html>
    `;
  },list:function(filelist){
    var list = '<ul>';
    var i = 0;
    while(i < filelist.length){
      list = list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
      i = i + 1;
    }
    list = list+'</ul>';
    return list;
  }
}

 

 

 

login을 클릭하면 로그인 할 수 있는 폼 창이 등장한다.

 

 

 

 

 

 

로그인이 정상적으로 완료되면 create, update 등등이 사용 가능해진다.

 

 

 

 

 

 

 

로그인 상태가 아니라면 create 나 update을 할 수 없고 위와 같은 에러 메세지를 등장시키도록 설정하였다.

 

 

 

 

 

 

잘못된 로그인 정보를 입력하면 에라 메시지를 등장시킨다.

 

 

 

 

반응형

댓글