Try to be the expert.

Ainsetin's Hacking & PS & Math

2020 Web Develop

웹개발 일지 13일차 (20.12.06)

Ainsetin 2020. 12. 6. 17:11

이번 프로젝트의 마지막 개발일지가 될듯 싶다. 1학기때는 로그인과 회원가입이 우선이었다면, 2학기때는 동적으로 작동하는 사이트 제작에 목표를 두었었다. 이번 1달 동안 드디어 CTF 카드 페이지를 동적으로 만드는데 성공하였다.

 

가장 먼저 수정했던 것은 "관리자만 카드를 추가할 수 있게끔 하는 것" 이었다. 그래서 DB에 관리자 리스트를 따로 만들어 로그인 직후 그 리스트 안에 자신의 ID가 있으면 관리자로 인식되게끔 하였다. SESSION의 level 값도 추가하여 1은 guest, 2는 admin으로 동작하게 하였다.

 

아래와 같이 코드를 작성하여 메인 header에서 나타나는 글자를 일반 유저와 관리자로 구분하였다.

 

간단하게 설명하자면, 로그인이 되고 나서 level을 비교하여 각각 다른 header 내용을 띄워주는 것이다.

카드가 나오는 find.php 페이지는 다음과 같이 로그인이 되어 있고 level이 2일 경우에만 카드 추가 버튼을 누를 수 있도록 수정하였다.

 


다음은 CTF card를 본격적으로 동적으로 만들기 위한 코드이다.

 

find.php의 card-form 부분. 사진을 누르면 더 깔끔하게 볼 수 있다.

최근에 작성한 카드가 먼저 나올 수 있도록 ORDER BY DESC를 sql문에 추가해 내림차순으로 query를 정렬하여 보이도록 하였다.

 

 

가장 중요한 점은 바로 페이징(paging)인데, 카드가 어느 정도 공간을 차지하고 있기 때문에 계속 스크롤해서 보여주는 것은 눈으로 보기에 불편하다. 그래서 쪽 번호를 만들어서 한 페이지에 9개만 나올 수 있도록 수정하였다.

 

또한, page를 get parameter로 받아와서 DB에 저장되어 있는 idx값이 1~9, 10~18, ... 으로 잘릴 수 있도록 $start 변수를 통해 구현하였다.

 

DB에 몇개의 데이터가 있는지 전송한 sql문의 query의 갯수를 파악한 후 페이지 번호를 출력해주는 코드를 추가로 작성하였다. search 파라미터가 세팅되어 있다면 그대로 가져와서 검색 결과 내의 page를 가져온다.


 

hidden으로 처리되어 있는 popup형 카드를 동적으로 불러오기 위해 다음과 같이 쿼리의 개수만큼 해당하는 팝업창을 로드시켜놓는 부분이다. 다음과 같이 작성하면 이제 카드가 잘 불러와질 것이다.

 

구현된 find.php의 모습
다음과 같이 새로운 카드가 생기면서 2페이지가 생겨나며, 내용에 따라 팝업이 잘 나타나는 것을 볼 수 있다.


마지막으로, 관리자 페이지를 prompt를 통해 만들어보았다.

코드는 다음과 같다.

 

<?php
  session_start();
  if(!isset($_SESSION['id']) || !isset($_SESSION['skill']) || $_SESSION['level']==1){
    echo "<script>alert(\"---------CENSORED---------\");</script>";
    echo "<script>location.href=\"/\";</script>";
  }
?>
<!DOCTYPE html>
<html>
  <head>
  </head>
  <body style="background-color: black;">
    <form id="add" method="POST">
      <input type="hidden" name="admin_id" id="admin_id">
    </form>
    <script>
      var menu=prompt("-----Admin Site-----\n1. print user\n2. print Admin\n3. add Admin\n4. delete Admin\n5. 돌아가기");
      
      if(menu=="1"){
        alert("-----유저 목록-----\n<?php
        session_start();
        header("Content-Type: text/html; charset=UTF-8");
        $conn = new mysqli("localhost","bww","CENSORED","user_list");
        mysqli_query($conn,'SET NAMES utf8');
        $sql="SELECT * FROM member";
        $res=$conn->query($sql);
        $i=1;
        while($row=mysqli_fetch_array($res)){
          echo $i.". ".$row['username']."\\n";
          $i=$i+1;
        }
      ?>");
        location.href="add_admin.php";
      }
      else if(menu=="2"){
        alert("-----관리자 목록-----\n<?php
        session_start();
        header("Content-Type: text/html; charset=UTF-8");
        $conn = new mysqli("localhost","bww","CENSORED","user_list");
        mysqli_query($conn,'SET NAMES utf8');
        $sql="SELECT * FROM admin_list";
        $res=$conn->query($sql);
        $i=1;
        while($row=mysqli_fetch_array($res)){
          echo $i.". ".$row['username']."\\n";
          $i=$i+1;
        }
      ?>");
        location.href="add_admin.php";
      }
      else if(menu=="3"){
        var select=prompt("Admin 목록에 추가할 id를 입력하세요.");
        //console.log(select);
        document.getElementById("admin_id").value=select;
        submitFormadd();
        function submitFormadd(){
          var formElement = document.querySelector("form");
          var formData = new FormData(formElement);
          var request = new XMLHttpRequest();
          request.open("POST", "admin_check.php");
          request.send(formData);
          request.onreadystatechange = function() {
            if (request.readyState == XMLHttpRequest.DONE) {
              if(request.responseText == "200"){
                alert('성공적으로 실행 되었습니다.');
              }
              else if(request.responseText == "400"){
                alert('그런 사용자는 없습니다.');
              }
              else if(request.responseText == "300"){
                alert('이미 Admin list에 해당 id가 존재합니다.');
              }
              location.href='add_admin.php';
            }
          }
        }
      }
      else if(menu=="4"){
        var select2=prompt("Admin 목록에서 삭제할 id를 입력하세요.");
        //console.log(select2);
        document.getElementById("admin_id").value=select2;
        submitFormdel();
        function submitFormdel(){
          var formElement = document.querySelector("form");
          var formData = new FormData(formElement);
          var request = new XMLHttpRequest();
          request.open("POST", "admin_delcheck.php");
          request.send(formData);
          request.onreadystatechange = function() {
            if (request.readyState == XMLHttpRequest.DONE) {
              if(request.responseText == "200"){
                alert('성공적으로 실행 되었습니다.');
              }
              else if(request.responseText == "400"){
                alert('그런 사용자는 없습니다.');
              }
              else{
                alert('최고 관리자의 admin 권한은 삭제할 수 없습니다.');
              }
              location.href='add_admin.php';
            }
          }
        }
      }
      else if(menu=="5"){
        alert('메인 화면으로 이동합니다.');
        location.href='/';
      }
      else{
        alert('유효하지 않는 메뉴입니다.');
        location.href='add_admin.php';
      }
    </script>
  </body>
</html>

 

위와 같이 javascript의 prompt로 팝업창에서 input을 받아올 수 있도록 하였고, 나머지 query를 가져오는 것이나 관리자 추가, 관리자 삭제는 php로 동작하게끔 하였다.

 

제일 기술적인 부분은 다른 php 파일에 접속하여 다른 파일로 경로가 이동되지 않아도 XMLHttpRequest()를 통해 그쪽으로 form data를 전달하여 responseText (echo로 무엇을 출력했는지)가 무엇인지를 판별하여 alert를 실행하는 매우 간편한 관리자 페이지를 완성시켰다는 것이다.

 

작동 과정은 다음 사진으로 살펴볼 수 있다.

 

메뉴창. 한 메뉴가 수행될때마다 반복된다.
1번 메뉴
2번 메뉴
3번 메뉴
4번 메뉴
최고 관리자 삭제 방지


채팅 기능을 만들까 고민하다 "응용프로그래밍 화면 구현"이라는 과목의 취지와 안 맞다고 생각해 과감하게 만들지 않기로 하였다. 이정도면 배운 것과 독학한 것을 바탕으로 잘 만들었다고 생각한다.

마무리하며,,

이번 1년동안 수행했던 긴 프로젝트를 이렇게 마무리할 수 있게 되어서 좋다. 처음에 프로젝트의 주제를 뭘 할까 고민하던 나의 모습이 아직까지도 기억이 나는데, 이렇게 많은 기능을 만들고 나니 개발에 흥미가 매우 많이 생겼고, 꿈꾸는 대로 만들 수 있는 개발의 힘을 느낄 수 있었다. 비록 수행평가라는 틀 안에서 이뤄낸 것이지만, 앞으로도 이와 같은 큰 프로젝트를 스스로 생각해 보면서 나만의 사이트, 다른 사람이 인정하는 사이트를 만들고 싶다.

 

(그러나, 이제 고3이다 으윽)