1. 필터

안정적인 프로그램의 동작을 위해서는 기반이 되는 정확한 값의 안전한 데이터가 중요합니다. 잘못된 데이터들을 프로그램의 예상치 않은 오동작을 발생시킬 수 있습니다.

프로그램 코드를 작성하다 보면 데이터의 정확한 유효성을 체크하는 작업을 자주합니다. 데이터를 일정한 패턴으로 검사를 하는 것은 그렇게 간단하지 않습니다. PHP는 데이터의 유효한 형식을 분석하고 패턴을 검사할 수 있는 필터 함수들을 제공합니다.

또한, 웹서비스 용도로 많이 사용하는 PHP 언어의 특성상 데이터는 외부의 HTML 폼 입력을 통하여도 많이 입력이 됩니다. 불특정한 다수의 사람들로부터 데이터를 입력을 받을 때 이러한 데이터의 유효성과 패턴은 더욱더 중요합니다.

일부 악의적인 사용자가 잘못된 코드로 프로그램의 오류를 발생시키거나, SQL 쿼리 기호들을 썩어서 입력함으로써 데이터베이스의 내용을 해킹할 수도 있습니다.

PHP는 제공되는 필터 내부함수를 통하여 간단하게 데이터의 패턴을 검사하여 유효성을 확인 할 수 있습니다. 필터 함수 기능들은 PHP 5.2.0부터는 기본적으로 설치가 되어 있습니다. 하지만, 필터 기능과 동작은 php.ini의 환경설정에 의해 약간의 영향을 받습니다 ini 설정은 다음과 같습니다:

filter.default filter.default 환경설정은 모든 $ _GET, $ _POST, $ _COOKIE, $ _REQUEST 및 $ _SERVER 데이터를 필터링 합니다. 필터 이름을 기본적으로 사용허용합니다.

filter.default_flags filter.default_flags 환경설정은 기본 필터로 설정이 된 경우 적용할 필터를 지정합니다. 이전 버전과의 호환성을 위해 기본적으로 FILTER_FLAG_NO_ENCODE_QUOTES로 설정됩니다.

01.1 필터의 유용성

필터는 데이터의 유효한 값을 간단하게 패턴 형태로 유효성 검사합니다. 필터 기능을 자주 적용하는 분야로는 웹을 데이터값을 입력 받는 분야일 것입니다. 웹서비스와 같은 응용서비스는 다양한 타입의 수많은 외부 데이터를 입력 받아 처리합니다.

 HTML 폼 입력값  쿠키값  API 데이터  서버 변수들  데이터베이스 결과값

위의 같은 값들은 외부로 입력 받을 수 있는 데이터의 유형들 입니다. 이러한 외부입력과 연관되는 데이터들을 항상 유효성 검사를 같이 하여 사용을 하는 것을 권장합니다. 유효성 검사 없이 데이터를 바로 사용을 할 경우에는, 악의적인 사용자로부터 입력 받은 데이터 값들이 프로그램의 문제를 발생하거나 해킹에 노출되게 됩니다.

01.1.1 필터목록

PHP의 필터들은 다양한 형태의 패턴들을 검사할 수 있습니다. 패턴을 검사 유형은 필터이름으로 구분을 합니다. 내부함수 filter_list()는 PHP 에서 지원하는 내장필터 목록을 출력합니다.

|내부함수| array filter_list ( void )

내부함수 filter_list()를 사용할때는 전달되는 입력 매개변수는 없습니다. 내장된 필터의 목록들을 배열형태로 반환을 합니다.

또한 내장된 필터명은 개발자들이 알기 쉽게 정의한 이름입니다. 이름들은 내부적으로 처리하는 고유의 ID값들로 다시 매칭이 되어 있씁니다. 내부함수 filter_id()는 입력된 필터명에 대해서 고유의 상수 ID 값을 확인할 수 있습니다.

|내부함수| int filter_id ( string $filtername )

예제파일) filter-01.php $filter) { echo "필터명 =" . $filter . ', ID=' . filter_id($filter) . '
'; } ?>

화면출력) 필터명 =int, ID=257 필터명 =boolean, ID=258 필터명 =float, ID=259 필터명 =validate_regexp, ID=272 필터명 =validate_domain, ID=277 필터명 =validate_url, ID=273 필터명 =validate_email, ID=274 필터명 =validate_ip, ID=275 필터명 =validate_mac, ID=276 필터명 =string, ID=513 필터명 =stripped, ID=513 필터명 =encoded, ID=514 필터명 =special_chars, ID=515 필터명 =full_special_chars, ID=522 필터명 =unsafe_raw, ID=516 필터명 =email, ID=517 필터명 =url, ID=518 필터명 =number_int, ID=519 필터명 =number_float, ID=520 필터명 =magic_quotes, ID=521 필터명 =callback, ID=1024

위의 실습코드는 내장된 필터의 목록과 필터명에 대한 고유한 ID값을 확인하는 예제 입니다. 이처럼 다양한 형태의 데이터 유효성을 검사할 수 있는 필터들을 제공합니다.

01.1.2 유효성검사

내부함수 filter_var()는 입력된 데이터를 지정한 필터형태의 패턴으로 데이터 유효성을 검사합니다.

|내부함수| mixed filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] )

함수의 매개변수 입력 값으로 두개의 값을 전달받습니다. 첫번째는 데이터 값은 검사유형 입니다. filter_var() 함수는 지정된 필터로 단일 변수만 필터링합니다.

01.2 필터상수

PHP는 filter_var() 함수를 통하여 필터링을 하기 위한 패턴유형을 상수명으로 제공합니다. 알기 쉬운 패턴코드들을 상수이름으로 정의하여 제공을 하는 것인 코드를 작성하는 측면에서 매우 유용합니다.

01.2.1 정수 확인 : FILTER_VALIDATE_INT

내부 필터함수 filter_var()는 입력되는 데이터 값이 정수형 타입인지를 확인할 수도 있습니다. 함수를 호출할 때 두번째 인자값으로 필터유형 FILTER_VALIDATE_INT를 사용하면 됩니다. 값의 정수 여부 판단은 논리값으로 반환을 합니다.

예제파일) filter-02.php <?php $int = 100;

if (!filter_var($int, FILTER_VALIDATE_INT) === false) {
		echo("정수가 유효합니다");
} else {
		echo("정수가 아닙니다");
} ?>

화면출력) 정수가 유효합니다

위의 실험은 입력 변수 $int의 데이터 값이 정수값 인지를 필터를 통하여 확인을 합니다. 만일 정수의 값이면 ture 반환값을 출력합니다.

수학에서 정수는 양수,0,음수 3가지로 구분을 합니다. ilter_var()는 양수와 음수만 정수값을 판별할 수 있습니다. 즉, 0의 값은 정수로 인식을 하지 못합니다. 따라서 이와 관련된 부가적인 코드를 같이 작성을 해야 합니다. 정수값 필터 사용시 === 0 조건과   연결을 결합하여 사용하는 것을 권장합니다.

예제파일) filter-03.php <?php $int = 0;

if (filter_var($int, FILTER_VALIDATE_INT) === 0 || 
	!filter_var($int, FILTER_VALIDATE_INT) === false) {
	echo("Integer is valid");
} else {
	echo("Integer is not valid");
} ?>

화면출력) Integer is valid

위 실험은 0의 정수값을 같이 판별을 하는 예제코드 입니다.

5.2.2 정수 확인 및 범위

컴퓨터에서 정수값을 사용할 때 표현을 할 수 있는 최대치의 범위가 있습니다. 또한 프로그램에서 입력의 임계치등의 범위가 필요할 경우가 있습니다. 이러한 경우에는 FILTER_VALIDATE_INT 값과 같이 세번째 매개변수를 통하여 범위값을 같이 전달할 수 있습니다.

배열 값을 응용하여 정수값 판별과 값의 범위 여부 내에 있는지 확인 할 수 있습니다.

예제파일) filter-04.php <?php $int = 122; $min = 1; $max = 200;

$range = array("options" => array("min_range"=>$min, "max_range"=>$max);
 
if (filter_var($int, FILTER_VALIDATE_INT, $range)) === false) {
		echo("변수 값이 유효한 범위 내에 있지 않습니다.!");
} else {
		echo("변수 값이 유효한 범위 내에 있습니다.!");
} ?>

화면출력) 변수 값이 유효한 범위 내에 있습니다.!

위의 실험은 필터함수 filter_var()를 사용하여 입력되는 데이터가 정수유형 인지와 1에서 200 사이의 값을 가지는지를 확인합니다.

그외 참고하여 같이 사용할 수 있는 필터상수는 다음과 같습니다:

 FILTER_VALIDATE_BOOLEAN : 논리값을 검사합니다.  FILTER_VALIDATE_FLOAT : float의 유효성을 검사합니다.  FILTER_SANITIZE_NUMBER_FLOAT : 숫자, + - 및 .e를 제외한 모든 문자를 제거합니다.  FILTER_SANITIZE_NUMBER_INT : 숫자와 + -를 제외한 모든 문자를 제거합니다.

01.2.3 IP주소 유효성 : FILTER_VALIDATE_IP

필터함수 filter_var()는 인터넷 IP 주소의 유형을 검사할 수 있습니다. 필터 상수명으로 FILTER_VALIDATE_IP 를 사용하게 되면 입력한 데이터가 IP 주소인지를 검사할 수 있습니다.

예제파일) filter-05.php <?php $ip = “127.0.0.1”;

if (!filter_var($ip, FILTER_VALIDATE_IP) === false) {
		echo("$ip 는 유효한 IP주소 입니다.");
} else {
		echo("$ip 는 유효하지 IP주소 입니다.");
} ?> 

화면출력) 127.0.0.1 는 유효한 IP주소 입니다.

5.2.4 IPv6 주소 유효성

IP에 대해서 IPv6 주소 타입 및 유효성을 같이 검사를 할 수 있습니다. IPv6 주소를 검사할때는 FILTER_VALIDATE_IP와 FILTER_FLAG_IPV6 두개의 값을 같이 이용을 합니다.

예제파일) filter-06.php <?php $ip = “2001:0db8:85a3:08d3:1319:8a2e:0370:7334”;

if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
	echo("$ip 는 유효한 IPv6 address");
} else {
	echo("$ip 는 유효하지 않는 IPv6 address");
} ?>

화면출력) 2001:0db8:85a3:08d3:1319:8a2e:0370:7334 는 유효한 IPv6 address

01.2.5 쿼리 스트링과 URL 유효성 검사 : FILTER_VALIDATE_URL

검사유형 FILTER_VALIDATE_URL 와 FILTER_FLAG_QUERY_REQUIRED 두개의 값을 통하여 URL 유효성과 이후 입력되는 GET 쿼리 스트링 데이터 값의 유효성 까지 함께 확인을 할 수 있습니다.

예제파일) filter-07.php <?php $url = “http://www.hojin.io”;

if (!filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED) === false) {
	echo("$url 유효한 URL");
} else {
	echo("$url 유효하지 않은 URL");
} ?>

화면출력) http://www.hojin.io 유효하지 않은 URL

다음 실험은 filter_var() 함수를 사용하여 문자열을 삭제합니다. 다음과 같이 문자열에서 모든 HTML 태그와 ASCII 값이 127보다 큰 모든 문자를 제거합니다.

예제파일) filter-08.php <?php $str = “<h1>Hello World!</h1>”;

$aaa = filter_var($str, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
echo $aaa; ?>

화면출력) Hello World!

01.2.6 이메일 주소 검사

내부함수 filter_var()를 통하여 이메일의 유효성을 검사할 수 있습니다. 이메일의 유효성을 검사할때는 필터상수 FILTER_VALIDATE_EMAIL를 사용합니다.

예제파일) filter-09.php <?php $email = “infohojin@naver.com”;

// 이메일에 포함된 부정한 글자들은 제거를 합니다.
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
 
// e-mail 유효성
if (!filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
	echo("$email is a valid email address");
} else {
	echo("$email is not a valid email address");
} ?>

화면출력) james.lee@example.com is a valid email address

그외 참고하여 같이 사용할 수 있는 필터상수는 다음과 같습니다:

 FILTER_SANITIZE_EMAIL : 부정한 글자를 제거합니다.  FILTER_VALIDATE_EMAIL : 전자 메일 주소 유효성 검사

01.2.7 문자열 체크 : FILTER_SANITIZE_STRING

입력한 값을 재출력하는 기능에서 잘못 입력되는 html 코드들은 오동작을 발생하게 됩니다. 내부함수 filter_var()를 통하여 입력된 문자열에서 HTML 코드를 제거할 수 있습니다.

예제파일) filter-10.php Hello World!"; $newstr = filter_var($str, FILTER_SANITIZE_STRING); echo $newstr; ?>

화면출력) Hello World!

필터상수 FILTER_SANITIZE_STRIPPED은 FILTER_SANITIZE_STRING의 별칭 입니다.

01.2.8 URL 유효성 검사

필터상수 FILTER_SANITIZE_URL 는 입력값의 URL 유효성 검사를 확인할 수 있습니다.

예제파일) filter-11.php <?php $url = “https://www.jinyphp.com”;

// Remove all illegal characters from a url
$url = filter_var($url, FILTER_SANITIZE_URL);
 
// Validate url
if (!filter_var($url, FILTER_VALIDATE_URL) === false) {
		echo("$url is a valid URL");
} else {
		echo("$url is not a valid URL");
} ?> 

화면출력) https://www. hojin.io is a valid URL

01.2.9 정규표현

필터상수 FILTER_VALIDATE_REGEXP는 입력된 데이터의 정규 표현식 유효성을 검사합니다.

01.2.10 특수문자

다음과 같은 필터상수를 통하여 입력되는 데이터의 특수문자들을 처리할 수 있습니다:

 FILTER_SANITIZE_ENCODED : 특수 문자를 제거 / 인코딩합니다.  FILTER_SANITIZE_SPECIAL_CHARS : 특수 문자를 제거합니다.  FILTER_UNSAFE_RAW : 별도의 작업없이, 선택적으로 특수 문자만 제거 / 인코딩합니다.  FILTER_SANITIZE_FULL_SPECIAL_CHARS

HTML 특수문자코드표

표현문자 숫자표현 문자표현 설명

  • - - 사용하지 않음 space - 수평탭 space - 줄 삽입
  • - - 사용하지 않음 space - 여백 ! ! - 느낌표 “ " " 따옴표

    # - 숫자기호

    $ $ - 달러 % % - 백분율 기호 & & & Ampersand ‘ ' - 작은 따옴표 ( ( - 왼쪽 괄호 ) ) - 오른쪽 괄호

  • * - 아스트릭
  • + - 더하기 기호 , , - 쉼표
  • - - Hyphen
    . . - 마침표
    / / - Solidus (slash)
    0 - 9 0-9 - 0부터 9까지
    : - 콜론 ; ; - 세미콜론 < < < 보다 작은 = = - 등호
    &#62;	&gt;	보다 큰 ?	&#63;	-	물음표 @	&#64;	-	Commercial at A - Z	&#65;-&#90;	-	A부터 Z까지 [	&#91;	-	왼쪽 대괄호 \	&#92;	-	역슬래쉬 ]	&#93;	-	오른쪽 대괄호 ^	&#94;	-	탈자부호 _	&#95;	-	수평선 `	&#96;	-	Acute accent a - z	&#97;-&#122;	-	a부터 z까지 {	&#123;	-	왼쪽 중괄호 |	&#124;	-	수직선 }	&#125;	-	오른쪽 중괄호 ~	&#126;	-	꼬리표
    
  • -Ÿ - 사용하지 않음     Non-breaking space ¡ ¡ ¡ 거꾸로된 느낌표 ¢ ¢ ¢ 센트 기호 £ £ £ 파운드 ¤ ¤ ¤ 현재 환율 ¥ ¥ ¥ 엔 | ¦ ¦ 끊어진 수직선 § § § 섹션 기호 ¨ ¨ ¨ 움라우트 ⓒ © © 저작권 ª ª ª Feminine ordinal ≪ « « 왼쪽 꺾인 괄호 ¬ ¬ ¬ 부정 ­ ­ ­ Soft hyphen ? ® ® 등록상표 &hibar; ¯ ¯ Macron accent ° ° ° Degree sign ± ± ± Plus or minus ² ² ² Superscript two ³ ³ ³ Superscript three ´ ´ ´ Acute accent μ µ µ Micro sign (Mu) ¶ ¶ ¶ 문단기호 · · · Middle dot ¸ ¸ ¸ Cedilla ¹ ¹ ¹ Superscript one º º º Masculine ordinal ≫ » » 오른쪽 꺾인 괄호 ¼ ¼ ¼ 4분의 1 ½ ½ ½ 2분의 1 ¾ ¾ ¾ 4분의 3 ¿ ¿ ¿ 거꾸로된 물음표 A À À Capital A, grave accent A Á Á Capital A, acute accent A Â Â Capital A, circumflex accent A Ã Ã Capital A, tilde A Ä Ä Capital A, dieresis or umlaut mark A Å Å Capital A, ring (Angstrom) Æ Æ Æ Capital AE diphthong (ligature) C Ç Ç Capital C, cedilla E È È Capital E, grave accent E É É Capital E, acute accent E Ê Ê Capital E, circumflex accent E Ë Ë Capital E, dieresis or umlaut mark I Ì Ì Capital I, grave accent I Í Í Capital I, acute accent I Î Î Capital I, circumflex accent I Ï Ï Capital I, dieresis or umlaut mark Ð Ð Ð Capital Eth, Icelandic N Ñ Ñ Capital N, tilde O Ò Ò Capital O, grave accent O Ó Ó Capital O, acute accent O Ô Ô Capital O, circumflex accent O Õ Õ Capital O, tilde O Ö Ö Capital O, dieresis or umlaut mark × × × Multiply sign Ø Ø Ø width=”130”Capital O, slash U Ù Ù Capital U, grave accent U Ú Ú Capital U, acute accent U Û Û Capital U, circumflex accent U Ü Ü Capital U, dieresis or umlaut mark Y Ý Ý Capital Y, acute accent Þ Þ Þ Capital Thorn, Icelandic ß ß ß Small sharp s, German (sz ligature) a à à Small a, grave accent a á á Small a, acute accent a â â Small a, circumflex accent a ã ã Small a, tilde a ä ä Small a, dieresis or umlaut mark a å å Small a, ring æ æ æ Small ae diphthong (ligature) c ç ç Small c, cedilla e è è Small e, grave accent e é é Small e, acute accent e ê ê Small e, circumflex accent e ë ë Small e, dieresis or umlaut mark i ì ì Small i, grave accent i í í Small i, acute accent i î î Small i, circumflex accent i ï ï Small i, dieresis or umlaut mark ð ð ð Small eth, Icelandic n ñ ñ Small n, tilde o ò ò Small o, grave accent o ó ó Small o, acute accent o ô ô Small o, circumflex accent o õ õ Small o, tilde o ö ö Small o, dieresis or umlaut mark ÷ ÷ ÷ Division sign ø ø ø Small o, slash u ù ù Small u, grave accent u ú ú Small u, acute accent u û û Small u, circumflex accent u ü ü Small u, dieresis or umlaut mark y ý ý Small y, acute accent þ þ þ Small thorn, Icelandic y ÿ ÿ Small y, dieresis or umlaut mark

01.2.11 함수적용

다음과 같은 필터 상수들은 함수를 별도의 함수를 적용하거나 호출을 할 수 있습니다.

 FILTER_SANITIZE_MAGIC_QUOTES: addslashes() 함수를 적용합니다.  FILTER_CALLBACK : 데이터 필터링을 위한 사용자 정의 함수를 호출합니다.

01.3 필터함수

PHP는 필터기능을 좀더 다양하게 처리를 하기 위해서 추가로 몇 개의 내부함수들을 제공합니다. 추가 함수들을 이용하면 복잡한 필터처리들을 보다 쉽게 구현을 할 수 있습니다.

|내부함수| bool filter_has_var ( int $type , string $variable_name )

내부함수 filter_has_var()는 지정된 타입유형의 변수가 있는지 확인합니다. 타입의 종류는 다음과 같습니다 :  INPUT_GET  INPUT_POST  INPUT_COOKIE  INPUT_SERVER, 또는 INPUT_ENV.

예제파일) filter-12.php

화면출력) INPUT_GET = Yes

위의 실습은 타입유형의 변수 존재 유무를 확인합니다. filter-12.php?aaa=test 형태로 GET 데이터를 추가하여 스크립트를 호출합니다. GET 방식으로 데이터를 전달과 변수명이 aaa 이기 때문 filter_has_var() 함수는 결과를 ‘참’ 으로 출력합니다.

|내부함수| mixed filter_input ( int $type , string $variable_name [, int $filter = FILTER_DEFAULT [, mixed $options ]] )

내부함수 filter_input()는 양식 입력등 처럼 외부 변수를 읽어와서 선택적으로 필터링합니다.

예제파일) filter-13.php <?php $search_html = filter_input(INPUT_GET, ‘search’, FILTER_SANITIZE_SPECIAL_CHARS); $search_url = filter_input(INPUT_GET, ‘search’, FILTER_SANITIZE_ENCODED);

echo "입력한 검색키워드는 $search_html 입니다.<br>";
echo "<a href='?search=$search_url'>재검색</a>"; ?>

위의 실험은 filter-13.php?search=jiny 형태로 GET 데이터를 추가하여 스크립트를 호출합니다.

|내부함수| mixed filter_input_array ( int $type [, mixed $definition [, bool $add_empty = true ]] )

내부함수 filter_input_array()는 필터를 처리하기 위한 배열 정보를 이용하여 다수의 외부변수를 일괄적으로 필터링합니다. 이 함수는 filter_input ()을 반복적으로 호출하지 않고도 많은 값을 검색 할 때 유용합니다.

예제파일) filter-14.php FILTER_SANITIZE_ENCODED, 'age' => FILTER_VALIDATE_INT, 'country' => FILTER_SANITIZE_ENCODED ); $myinputs = filter_input_array(INPUT_GET, $args); var_dump($myinputs); ?>

화면출력) array(3) { [“name”]=> string(4) “jiny” [“age”]=> int(18) [“country”]=> string(5) “korea” }

위의 실험은 filter-14.php?name=jiny&age=18&country=korea 형태로 GET 데이터를 추가하여 스크립트를 호출합니다.

|내부함수| mixed filter_var_array ( array $data [, mixed $definition [, bool $add_empty = true ]] )

내부변수 filter_var_array()는 여러개의 변수를 필터링합니다. 이 함수는 filter_var ()를 반복적으로 호출하지 않고도 많은 값을 검색하는 데 유용합니다. 아래 예제는 공식사이트에 있는 예제입니다.

예제파일) filter-15.php <?php error_reporting(E_ALL | E_STRICT); $data = array( ‘product_id’ => ‘libgd

$args = array(
'product_id'   => FILTER_SANITIZE_ENCODED,
'component'    => array('filter'    => FILTER_VALIDATE_INT,
                        'flags'     => FILTER_FORCE_ARRAY,
                        'options'   => array('min_range' => 1, 'max_range' => 10)
                       ),
'versions'     => FILTER_SANITIZE_ENCODED,
'doesnotexist' => FILTER_VALIDATE_INT,
'testscalar'   => array(
                        'filter' => FILTER_VALIDATE_INT,
                        'flags'  => FILTER_REQUIRE_SCALAR,
                       ),
'testarray'    => array(
                        'filter' => FILTER_VALIDATE_INT,
                        'flags'  => FILTER_FORCE_ARRAY,
                       )

                   );

$myinputs = filter_var_array($data, $args);

var_dump($myinputs);
echo "\n"; ?>

화면출력) array(6) { [“product_id”]=> string(17) “libgd%3Cscript%3E” [“component”]=> array(1) { [0]=> int(10) } [“versions”]=> string(6) “2.0.33” [“doesnotexist”]=> NULL [“testscalar”]=> bool(false) [“testarray”]=> array(1) { [0]=> int(2) } }