Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

9시 24분

저자 관리 기능 구현 - CRUD & SQL injection 본문

Javascript/Node.js

저자 관리 기능 구현 - CRUD & SQL injection

leeeee.yeon 2021. 7. 6. 11:05

저자 목록을 보고, 저자를 생성/수정/삭제하는 기능을 구현하자.

 

1. 저자 목록 보기

 

< author.js 추가 >

var db = require('./db');
var template = require('./template.js');

exports.home = function(request, response){
    db.query(`SELECT * FROM topic`, function(error, topics){
        if(error) throw error;
        db.query(`SELECT * FROM author`, function(error2, authors){
            if(error2) throw error2;

            var title = 'Author';
            var list = template.list(topics);
            var html = template.HTML(title, list,
              `
                ${template.authorTable(authors)}
                <style>
                table{
                    border-collapse: collapse;
                }
                td{
                    border:1px solid black;
                }
                </style>
                `,
                `<a href="/create">create</a>`
            );
            response.writeHead(200);
            response.end(html);
        });
      }); 
}

 

< template.js 추가 >

  ,authorTable:function(authors){
    var tag = '<table>';
    var i = 0;
    while(i<authors.length){
        tag += `
        <tr>
            <td>${authors[i].name}</td>
            <td>update</td>
            <td>delete</td>
        </tr>
      `;
      i++;
    }
    tag += '</table>';

    return tag;
  }

 

< main.js 수정 >

else if(pathname === '/author'){
        author.home(request, response);
    }

 

2. 생성

exports.create_process = function(request, response){
    var body = '';
    request.on('data', function(data){
        body = body + data;
    });
    request.on('end', function(){
        var post = qs.parse(body);
        
        db.query(`
          INSERT INTO author (name)
            VALUES(?)`,
            [post.name],
            function(error, result){
              if(error) throw error;
              response.writeHead(302, {Location: `/author`});
              response.end();
            }
            );
    });
}
  • 자세한 설명은 생략했지만 필요한 모듈 불러오고, main.js랑 exports.home도 알맞게 수정해주어야 함

 

3. 수정

exports.update = function(request, response){
    db.query(`SELECT * FROM topic`, function(error, topics){
        if(error) throw error;
        db.query(`SELECT * FROM author`, function(error2, authors){
            if(error2) throw error2;
            var _url = request.url;
            var queryData = url.parse(_url, true).query;
            db.query(`SELECT * FROM author WHERE id=?`,[queryData.id], function(error3, author){
                if(error3) throw error3;
                var title = 'Author';
                var list = template.list(topics);
                var html = template.HTML(title, list,
                  `
                    ${template.authorTable(authors)}
                    <style>
                    table{
                        border-collapse: collapse;
                    }
                    td{
                        border:1px solid black;
                    }
                    </style>
                    
                    <form action="/author/update_process" method="post">
                        <p>
                            <input type="hidden" name="id" value="${queryData.id}">
                        <p>
                        <p>
                            <input type="text" name="name" value="${author[0].name}" placeholder="name">
                        <p>
                        <p>
                            <input type="submit" value="update">
                        <p>
                    </form>
                    `,
                    ``
                );
                response.writeHead(200);
                response.end(html);
            });
        });
      }); 
}

exports.update_process = function(request, response){
    var body = '';
    request.on('data', function(data){
        body = body + data;
    });
    request.on('end', function(){
        var post = qs.parse(body);
        
        db.query(`
          UPDATE author SET name=? WHERE id=?`,
            [post.name, post.id],
            function(error, result){
              if(error) throw error;
              response.writeHead(302, {Location: `/author`});
              response.end();
            }
            );
    });
}

4. 삭제

exports.delete_process = function(request, response){
    var body = '';
    request.on('data', function(data){
        body = body + data;
    });
    request.on('end', function(){
        var post = qs.parse(body);
        var id = post.id;
        db.query(`DELETE FROM topic WHERE author_id=?`,
        [post.id], function(error1, result){
            if(error1) throw error1;
            db.query(`DELETE FROM author WHERE id=?`, [post.id], function(error2, result){
                if(error2) throw error;
                response.writeHead(302, {Location: `/author`});
                response.end();
              });
        });
    });
}
  • 저자 삭제 + 작성한 글도 함께 삭제

 

SQL injection

URL에 이렇게 입력할 시 db에 전달되는 query는

SELECT *
FROM topic
LEFT JOIN author ON topic.author_id=author id
WHERE topic.id='1;DROP TABLE topic;'

이 되기 때문에 topic 테이블이 삭제될 수 있다. 하지만 아래와 같이 ?를 쓰고 인자를 뒤에 쓰는 방식으로 SQL injection을 방지할 수 있다.

 

db.query(`DELETE FROM author WHERE id=?`, [post.id], function(error2, result){
if(error2) throw error;
response.writeHead(302, {Location: `/author`});
response.end();
});

 

escaping 기법

 

입력으로부터의 보안을 위해 sanitize-html 모듈을 이용

sanitize-html 모듈의 sanitizeHtml() 함수를 topics[0].title, author[0].name 등 입력이 들어올 수 있는 부분에 씌우자.

id와 같이 auto-increment인 요소는 자동 입력(사용자가 입력하지 않음)이기 때문에 sanitize 해주지 않아도 된다.

 

MySQL 수업 끝 ~~~


(+) 수업을 마치며

검색 기능 - form 태그, get 방식 전송, SELECT * FROM topic WHERE title="keyword"

index 기능

정렬 기능 - SELECT * FROM topic ORDER BY id DESC

페이징 기능 - SELECT * FROM topic LIMIT 0 OFFSET 20