기타/WWW

PHP 5 투토리얼 (2) - 폼

하늘이푸른오늘 2014. 6. 22. 23:49

웹페이지를 제작하기 위해서는 크게 두가지 작업이 필요합니다. 하나는 서버측 프로그래밍이고, 다른 하나는 클라이언트측 프로그래밍입니다.


원칙적으로 서버측에서는 데이터 그 자체를 다루고, 클리이언트 측에서는 그 데이터를 어떻게 표현하는가를 다루므로, 서버측이 더 중요하다고 볼 수 있습니다.


서버측 프로그램은 여러가지 언어로 개발될 수 있지만, 가장 널리 사용되는 것이 PHP (PHP HyperText Preprocessor)입니다. 이전에는 기본적인 사항을 다루었고, 이번엔 두번째로 Form을 처리하는 방법입니다.


PHP - A Simple HTML Form

다음 예제는 두개의 input 필드와 submit 버튼이 있는 폼


<html>

<body>


<form action="welcome.php" method="post">

Name: <input type="text" name="name"><br>

E-mail: <input type="text" name="email"><br>

<input type="submit">

</form>


</body>

</html>


사용자가 input 필드를 채우고 submit 버튼을 누르면, form 데이터가 action에서 지정한 welcome.php 로 전달됨. 이 폼은 POST 으로 전송됨.

아래는 welcome.php 의 내용임


<html>

<body>


Welcome <?php echo $_POST["name"]; ?><br>

Your email address is: <?php echo $_POST["email"]; ?>


</body>

</html>


====

HTTP GET을 사용해도 동일한 처리가 가능함


<html>

<body>


<form action="welcome_get.php" method="get">

Name: <input type="text" name="name"><br>

E-mail: <input type="text" name="email"><br>

<input type="submit">

</form>


</body>

</html>


아래는 이에 대응되는 welcome.php 의 내용


<html>

<body>


Welcome <?php echo $_GET["name"]; ?><br>

Your email address is: <?php echo $_GET["email"]; ?>


</body>

</html>


***** 위의 내용에서는 없지만, 보안을 위하여 반드시 Form validation 이 필요함. 

GET vs. POST

GET과 POST는 모두 배열( 예: array( key => value, key2 => value2, key3 => value3, ...)) 를 생성함. 이 배열에는 key/value 쌍이 저장되어 있음. 여기에서 key는 폼의 control 이름. values는 사용자가 입력한 데이터. 


GET과 POST는 $_GET, $_POST를 사용하여 처리됨. $_GET과 $_POST는 super 전역변수(변수범위에 관계없이 어디에서나 접근 가능) 


$_GET은 URL 파라미터를 통해 현재 script에 전달된 변수의 배열

$_POST는 HTTP POST 메소드를 통해 현재 script에 전달된 변수의 배열


GET 메소드를 통해 폼에 전달된 정보는 누구나 볼수 있음(변수와 값이 URL에 표시됨). 보낼 수 있는 정보의 양도 약 2000 문자로 제한됨. 하지만, 변수가 모두 보이므로 북마크가 가능함. GET은 민감하지 않은 자료를 보낼 때 사용가능


POST 메소드로 전달된 정보는 아무에게도 안보임. (키/값 이 모두 HTTP request의 몸체속에 내장됨.) 보낼 수 있는 정보의 양도 제한이 없음. 


아울러 파일을 서버에 올릴 때 multi-part binary input을 지원하는 등 고급 기능을 지원함. 


그러나, 북마크는 불가능함. 대부분의 개발자들은 POST를 더 좋아하는 편


PHP Form Validation

해커와  스패머를 막기 위해서는 적절한 처리가 필요.


폼의 형태

<h2>PHP Form Validation Example</h2>

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>"> 

   Name: <input type="text" name="name">

   <br><br>

   E-mail: <input type="text" name="email">

   <br><br>

   Website: <input type="text" name="website">

   <br><br>

   Comment: <textarea name="comment" rows="5" cols="40"></textarea>

   <br><br>

   Gender:

   <input type="radio" name="gender" value="female">Female

   <input type="radio" name="gender" value="male">Male

   <br><br>

   <input type="submit" name="submit" value="Submit"> 

</form>


<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">

  • From이 제출되면 POST 메소드로 전송됨
  • $_SERVER["PHP_SELF"] 는 현재 수행되는 스크립트의 파일명 을 돌려주는 super 전역변수.
  • 따라서 form 데이터를 자기 자신에 돌려줌. 이렇게 하면 에러메시지를 현재 페이지에서 볼 수 있음
  • htmlspecialchars()는 special character를 HTML 엔터티로 변환. 즉, <, > 등을 &lt, &gt 등으로 변환. 이렇게 해야만, 해커들이 폼에 HTML이나 Javascript를 삽입함으로써 코드를 도용하는 것(Cross-site Scripting Attacks)을 막을 수 있음

PHP Form 의 보안문제

  • $_SERVER["PHP_SELF"] 변수는 해커의 표적이 될 수 있음.
    • /를 넣고, XSS(Cross site scripting) 명령을 삽입시킬 수 있음
    • test_form.php 내에 <form method="post" action="<?php echo $_SERVER["PHP_ERVER"];?>"> 라고 정의 되어 있다고 가정하면,  일반적으로는 <form method="post" action="test_from.php">로 해석되므로 문제가 없음
    • 그런데 주소에 다음처럼 넣었다고 하면...
    • http://www.example.com/test_from.php/%22%3E%3Cscript%3Ealert('hacked')%3C/script%3E
    • <form method="post" action="test_form.php"/><scprit>alert('hacked')</script> 처럼 해킹되어버림.
  • 먼저 모든 변수를 htmlspecialchars()을 사용해 걸러내면 막을 수 있음
    • <form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_ERVER"]);?>">
    • 그러면 <form method="post: action="test_form.php/&quot;&gt;&lt;.... 으로 해석되므로 문제가 없음

    PHP를 이용한 Form 데이터 검증

    • 가장 먼저 모든 변수를 htmlspecialchars()로 처리한 뒤 사용
    • PHP trim()을 사용하여, 사용자 입력자료에서 공백, 탭, 등을 제거 
    • PHP stripslashes()를 사용하여 '\'를 제거
    • 이 세가지 기능을 처리하는 함수를 작성하여 사용

    <?php

    $name = $email = $website = $comment = $gender = "";


    if ($SERVER["REQUEST_METHOD"] == "POST"){

    $name = test_input($POST["name"]);

    $email = test_input($POST["email"]);

    ....

    }


    function test_input($data){

      $data = trim($data);

      $data = stripslashes($data);

      $data = htmlspecialchars($data);

      return $data;

    }

    ?>


    Required Field

    • if (empty($POST["name"])) 로 테스트하여 처리


    <?php

    $nameErr = $emailErr = $websiteErr = $commentErr = $genderErr = "";

    $name = $email = $website = $comment = $gender = "";


    if ($SERVER["REQUEST_METHOD"] == "POST"){

    if (empty($POST["name"])) {

    $nameErr = "Name is required";

    } else {

         $name = test_input($POST["name"]);

    }

    ....

    }

    ?>


    • 그리고 Form에서 에러메시지를 받아서 표시하도록 함.


    <form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>"> 

       Name: <input type="text" name="name">

       <span class="error">* <?php echo $nameErr;?></span>

       <br><br>

       E-mail: <input type="text" name="email">

       <span class="error">* <?php echo $emailErr;?></span>

       <br><br>

        ....

    </form>


    • 그러나, 이와같은 Form의 항목 점검은 클라이언트 쪽에서 javascript로 처리하는 게 나을 것 같음

    Name 처리

    • 모두 영문자 또는 공백의 경우

    $name = test_input($POST["name"]);

    if(!preg_match("/^[a-zA-Z ]*$/", $name) {

    $nameErr ="Only letters and white spaces allowed";

    }

    • Email 의 경우 : if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email))
    • URL의 경우 if (!preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i",$website)):