코딩 스쿨 PHP

언어선택 : HTMLCSSJAVAJAVASCRIPTMYSQLSQL PHP

PHP Filter

PHP 필터 참조: 데이터 검증 및 정화를 위한 강력한 도구


  • *PHP 필터(Filter)**는 사용자 입력 데이터를 검증하고 정화하는 데 사용되는 강력한 기능을 제공합니다. PHP의 필터 확장을 활용하면 데이터의 유효성을 검사하고, 잠재적인 보안 위협을 줄이며, 애플리케이션의 안정성을 높일 수 있습니다. 이 가이드는 PHP 필터의 주요 기능과 사용법을 상세히 설명하며, 실용적인 예제를 통해 효과적으로 활용하는 방법을 제시합니다.

1. PHP 필터의 기본 이해

1.1 필터란?

필터는 데이터를 검증하고 정화하는 메커니즘으로, 사용자 입력이나 외부 소스로부터 받은 데이터를 안전하게 처리하는 데 사용됩니다. PHP는 내장된 다양한 필터를 제공하며, 필요에 따라 사용자 정의 필터도 생성할 수 있습니다.

1.2 필터의 종류

  1. 검증 필터(Validation Filters): 데이터가 특정 기준을 충족하는지 확인합니다.
  2. 정화 필터(Sanitization Filters): 데이터에서 불필요하거나 위험한 문자를 제거하여 안전하게 만듭니다.
  3. 기타 필터: 특정 상황에 맞는 커스텀 필터를 생성하여 사용할 수 있습니다.

2. PHP 필터 함수

2.1 filter_var()

filter_var() 함수는 단일 변수를 필터링하는 데 사용됩니다. 이 함수는 변수의 값을 지정된 필터로 검증하거나 정화합니다.

사용 예시: 이메일 검증

<?php
$email = "user@example.com";

if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "유효한 이메일 주소입니다.";
} else {
    echo "유효하지 않은 이메일 주소입니다.";
}
?>

설명:

  • FILTER_VALIDATE_EMAIL 필터를 사용하여 이메일 형식을 검증합니다.
  • 유효한 이메일인 경우 true, 그렇지 않으면 false를 반환합니다.

2.2 filter_input()

filter_input() 함수는 특정 입력 소스에서 변수를 가져와 필터링합니다. 주로 폼 데이터나 URL 매개변수를 처리할 때 사용됩니다.

사용 예시: GET 요청의 이메일 파라미터 검증

<?php
$email = filter_input(INPUT_GET, 'email', FILTER_VALIDATE_EMAIL);

if ($email) {
    echo "유효한 이메일 주소: " . htmlspecialchars($email);
} else {
    echo "유효하지 않은 이메일 주소입니다.";
}
?>

설명:

  • INPUT_GET을 사용하여 GET 요청의 'email' 파라미터를 가져옵니다.
  • FILTER_VALIDATE_EMAIL 필터로 이메일을 검증합니다.
  • htmlspecialchars() 함수를 사용하여 출력 시 HTML 특수 문자를 이스케이프합니다.

2.3 filter_input_array()

filter_input_array() 함수는 여러 입력 변수를 한 번에 필터링할 때 사용됩니다. 배열을 통해 각 변수에 대한 필터를 지정할 수 있습니다.

사용 예시: POST 요청의 여러 변수 필터링

<?php
$filters = [
    'email' => FILTER_VALIDATE_EMAIL,
    'age' => [
        'filter' => FILTER_VALIDATE_INT,
        'options' => ['min_range' => 18, 'max_range' => 100]
    ]
];

$inputs = filter_input_array(INPUT_POST, $filters);

if ($inputs) {
    if ($inputs['email'] && $inputs['age']) {
        echo "이메일과 나이가 유효합니다.";
    } else {
        echo "이메일 또는 나이가 유효하지 않습니다.";
    }
} else {
    echo "입력 데이터를 필터링하는 데 실패했습니다.";
}
?>

설명:

  • FILTER_VALIDATE_EMAILFILTER_VALIDATE_INT를 사용하여 이메일과 나이를 각각 검증합니다.
  • 나이에 대한 추가 옵션으로 최소값과 최대값을 설정합니다.

2.4 filter_var_array()

filter_var_array() 함수는 배열 형태의 데이터를 한 번에 필터링할 때 사용됩니다. filter_input_array()와 유사하지만, 입력 소스가 아닌 배열 자체를 필터링합니다.

사용 예시: 사용자 입력 배열 정화

<?php
$input = [
    'name' => '<b>John Doe</b>',
    'email' => 'john.doe@example.com',
    'age' => '25'
];

$filters = [
    'name' => FILTER_SANITIZE_STRING,
    'email' => FILTER_VALIDATE_EMAIL,
    'age' => FILTER_VALIDATE_INT
];

$sanitized = filter_var_array($input, $filters);

print_r($sanitized);
?>

출력 예시:

Array
(
    [name] => John Doe
    [email] => john.doe@example.com
    [age] => 25
)

설명:

  • FILTER_SANITIZE_STRING을 사용하여 이름에서 HTML 태그를 제거합니다.
  • 이메일과 나이를 각각 검증합니다.

3. PHP 필터 종류

3.1 검증 필터 (Validation Filters)

검증 필터는 데이터가 특정 기준을 충족하는지 확인하는 데 사용됩니다.

  • FILTER_VALIDATE_BOOLEAN: 불리언 값으로 검증합니다.
  • FILTER_VALIDATE_EMAIL: 유효한 이메일 주소인지 확인합니다.
  • FILTER_VALIDATE_FLOAT: 실수형 값으로 검증합니다.
  • FILTER_VALIDATE_INT: 정수형 값으로 검증합니다.
  • FILTER_VALIDATE_IP: 유효한 IP 주소인지 확인합니다.
  • FILTER_VALIDATE_URL: 유효한 URL인지 확인합니다.

예시: IP 주소 검증

<?php
$ip = "192.168.1.1";

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

3.2 정화 필터 (Sanitization Filters)

정화 필터는 데이터에서 불필요하거나 위험한 문자를 제거하여 안전하게 만듭니다.

  • FILTER_SANITIZE_EMAIL: 이메일 주소를 정화합니다.
  • FILTER_SANITIZE_ENCODED: URL 인코딩을 수행합니다.
  • FILTER_SANITIZE_NUMBER_FLOAT: 실수형 숫자만 남깁니다.
  • FILTER_SANITIZE_NUMBER_INT: 정수형 숫자만 남깁니다.
  • FILTER_SANITIZE_SPECIAL_CHARS: HTML 특수 문자를 이스케이프합니다.
  • FILTER_SANITIZE_STRING: 문자열에서 불필요한 문자를 제거합니다.
  • FILTER_SANITIZE_URL: URL을 정화합니다.

예시: 문자열 정화

<?php
$input = "<h1>Hello, World!</h1>";

$sanitized = filter_var($input, FILTER_SANITIZE_STRING);
echo $sanitized; // 출력: Hello, World!
?>

3.3 기타 필터

  • FILTER_CALLBACK: 사용자 정의 콜백 함수를 사용하여 데이터를 필터링합니다.

예시: 사용자 정의 필터 사용

<?php
function remove_spaces($value) {
    return str_replace(' ', '', $value);
}

$input = "Hello World";

$sanitized = filter_var($input, FILTER_CALLBACK, [
    'options' => 'remove_spaces'
]);

echo $sanitized; // 출력: HelloWorld
?>


4. PHP 필터 옵션 및 플래그

PHP 필터를 사용할 때 다양한 옵션과 플래그를 설정하여 필터의 동작을 세밀하게 제어할 수 있습니다.

4.1 필터 옵션

필터 옵션을 사용하여 필터의 동작을 조정할 수 있습니다.

  • options: 필터의 세부 동작을 설정합니다.
  • flags: 필터의 추가적인 동작을 지정합니다.

예시: 정수 검증 시 범위 설정

<?php
$age = 25;

$options = [
    'options' => [
        'min_range' => 18,
        'max_range' => 99
    ]
];

if (filter_var($age, FILTER_VALIDATE_INT, $options)) {
    echo "유효한 나이입니다.";
} else {
    echo "유효하지 않은 나이입니다.";
}
?>

설명:

  • min_rangemax_range 옵션을 사용하여 나이의 범위를 제한합니다.
  • 나이가 18 이상 99 이하인 경우에만 유효한 것으로 간주합니다.

4.2 필터 플래그

필터 플래그는 필터의 추가적인 동작을 지정하는 설정입니다.

  • FILTER_FLAG_ALLOW_FRACTION: 실수형 숫자에서 소수점을 허용합니다.
  • FILTER_FLAG_ALLOW_THOUSAND: 실수형 숫자에서 천 단위 구분 기호를 허용합니다.
  • FILTER_FLAG_STRIP_LOW: 저수준 문자를 제거합니다.
  • FILTER_FLAG_STRIP_HIGH: 고수준 문자를 제거합니다.
  • FILTER_FLAG_ENCODE_LOW: 저수준 문자를 HTML 엔티티로 변환합니다.
  • FILTER_FLAG_ENCODE_HIGH: 고수준 문자를 HTML 엔티티로 변환합니다.

예시: 실수형 숫자 검증 시 소수점과 천 단위 구분 기호 허용

<?php
$price = "1,234.56";

$options = [
    'options' => [
        'decimal' => '.',
        'thousands' => ','
    ],
    'flags' => FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND
];

$validatedPrice = filter_var($price, FILTER_VALIDATE_FLOAT, $options);

if ($validatedPrice !== false) {
    echo "유효한 가격: " . $validatedPrice;
} else {
    echo "유효하지 않은 가격 형식입니다.";
}
?>

설명:

  • FILTER_FLAG_ALLOW_FRACTIONFILTER_FLAG_ALLOW_THOUSAND를 사용하여 소수점과 천 단위 구분 기호를 허용합니다.
  • FILTER_VALIDATE_FLOAT를 사용하여 실수형 숫자를 검증합니다.

5. 사용자 정의 필터

PHP에서는 FILTER_CALLBACK을 사용하여 사용자 정의 필터를 생성할 수 있습니다. 이를 통해 복잡한 데이터 처리 로직을 필터에 통합할 수 있습니다.

예시: 사용자 정의 이메일 필터

<?php
function custom_email_filter($email) {
    // 이메일에서 특정 도메인을 허용
    if (strpos($email, '@example.com') !== false) {
        return filter_var($email, FILTER_SANITIZE_EMAIL);
    } else {
        return false;
    }
}

$email = "user@example.com";

$filteredEmail = filter_var($email, FILTER_CALLBACK, [
    'options' => 'custom_email_filter'
]);

if ($filteredEmail) {
    echo "정화된 이메일: " . htmlspecialchars($filteredEmail);
} else {
    echo "허용되지 않는 이메일 도메인입니다.";
}
?>

설명:

  • custom_email_filter 함수는 이메일 주소에 특정 도메인이 포함되어 있는지 확인합니다.
  • 조건을 만족하면 FILTER_SANITIZE_EMAIL을 적용하여 이메일을 정화하고, 그렇지 않으면 false를 반환합니다.

6. 실용적인 예제

6.1 사용자 입력 검증 및 정화

사용자 등록 폼에서 입력된 데이터를 검증하고 정화하는 예제입니다.

HTML 폼: 사용자 등록

<!DOCTYPE html>
<html>
<head>
    <title>사용자 등록</title>
</head>
<body>
    <h2>사용자 등록</h2>
    <form action="register.php" method="post">
        이름: <input type="text" name="name"><br><br>
        이메일: <input type="text" name="email"><br><br>
        나이: <input type="text" name="age"><br><br>
        <input type="submit" value="등록">
    </form>
</body>
</html>

PHP 스크립트: register.php

<?php
// 필터 정의
$filters = [
    'name' => FILTER_SANITIZE_STRING,
    'email' => FILTER_VALIDATE_EMAIL,
    'age' => [
        'filter' => FILTER_VALIDATE_INT,
        'options' => ['min_range' => 18, 'max_range' => 100]
    ]
];

// 입력 필터링
$inputs = filter_input_array(INPUT_POST, $filters);

// 검증 결과 확인
if ($inputs) {
    if ($inputs['name'] && $inputs['email'] && $inputs['age']) {
        echo "사용자 등록이 성공적으로 완료되었습니다.<br>";
        echo "이름: " . htmlspecialchars($inputs['name']) . "<br>";
        echo "이메일: " . htmlspecialchars($inputs['email']) . "<br>";
        echo "나이: " . htmlspecialchars($inputs['age']) . "세";
    } else {
        echo "입력 데이터가 유효하지 않습니다.<br>";
        if (!$inputs['name']) {
            echo "이름을 확인해주세요.<br>";
        }
        if (!$inputs['email']) {
            echo "유효한 이메일 주소를 입력해주세요.<br>";
        }
        if (!$inputs['age']) {
            echo "나이는 18세 이상 100세 이하이어야 합니다.<br>";
        }
    }
} else {
    echo "입력 데이터를 필터링하는 데 실패했습니다.";
}
?>

설명:

  • FILTER_SANITIZE_STRING을 사용하여 이름을 정화하고, FILTER_VALIDATE_EMAIL로 이메일을 검증합니다.
  • 나이에 대해서는 정수형으로 검증하고, 18세 이상 100세 이하인지 확인합니다.
  • 모든 검증을 통과한 경우 사용자 등록을 완료하고, 그렇지 않으면 적절한 오류 메시지를 표시합니다.

6.2 배열 필터링

다수의 사용자 데이터를 배열 형태로 필터링하는 예제입니다.

PHP 스크립트: 배열 데이터 필터링

<?php
$data = [
    'username' => 'john_doe',
    'email' => 'john.doe@example.com',
    'age' => '30',
    'website' => '<https://www.example.com>'
];

$filters = [
    'username' => [
        'filter' => FILTER_SANITIZE_STRING,
        'flags' => FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH
    ],
    'email' => FILTER_VALIDATE_EMAIL,
    'age' => [
        'filter' => FILTER_VALIDATE_INT,
        'options' => ['min_range' => 18, 'max_range' => 100]
    ],
    'website' => FILTER_VALIDATE_URL
];

$sanitized = filter_var_array($data, $filters);

print_r($sanitized);
?>

출력 예시:

Array
(
    [username] => john_doe
    [email] => john.doe@example.com
    [age] => 30
    [website] => <https://www.example.com>
)

설명:

  • 배열 형태의 데이터를 한 번에 필터링하여 각 필드에 맞는 검증과 정화를 수행합니다.
  • FILTER_FLAG_STRIP_LOWFILTER_FLAG_STRIP_HIGH를 사용하여 username에서 저수준 및 고수준 문자를 제거합니다.

6.3 필터 체인

여러 필터를 연속적으로 적용하여 데이터를 처리하는 예제입니다.

PHP 스크립트: 필터 체인 사용

<?php
$input = " <script>alert('XSS');</script> john.doe@example.com ";

$sanitized = filter_var(trim($input), FILTER_SANITIZE_STRING);
$sanitizedEmail = filter_var($sanitized, FILTER_VALIDATE_EMAIL);

if ($sanitizedEmail) {
    echo "정화된 이메일: " . htmlspecialchars($sanitizedEmail);
} else {
    echo "유효하지 않은 이메일 주소입니다.";
}
?>

설명:

  • trim() 함수를 사용하여 입력의 앞뒤 공백을 제거합니다.
  • FILTER_SANITIZE_STRING을 사용하여 스크립트 태그를 제거합니다.
  • FILTER_VALIDATE_EMAIL로 이메일을 검증합니다.
  • 최종적으로 정화된 이메일을 출력합니다.

7. PHP 필터 확장: filter_var_array()filter_input_array()

7.1 filter_var_array()

filter_var_array() 함수는 배열 형태의 데이터를 한 번에 필터링할 때 사용됩니다. 각 배열 요소에 대해 별도의 필터를 적용할 수 있습니다.

사용 예시: 여러 필드 필터링

<?php
$data = [
    'username' => 'john_doe',
    'email' => 'john.doe@example.com',
    'age' => '30',
    'website' => '<https://www.example.com>'
];

$filters = [
    'username' => FILTER_SANITIZE_STRING,
    'email' => FILTER_VALIDATE_EMAIL,
    'age' => FILTER_VALIDATE_INT,
    'website' => FILTER_VALIDATE_URL
];

$sanitized = filter_var_array($data, $filters);

print_r($sanitized);
?>

출력 예시:

Array
(
    [username] => john_doe
    [email] => john.doe@example.com
    [age] => 30
    [website] => <https://www.example.com>
)

7.2 filter_input_array()

filter_input_array() 함수는 특정 입력 소스에서 여러 변수를 한 번에 필터링할 때 사용됩니다. 주로 INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV와 함께 사용됩니다.

사용 예시: POST 요청의 여러 변수 필터링

<?php
$filters = [
    'username' => FILTER_SANITIZE_STRING,
    'email' => FILTER_VALIDATE_EMAIL,
    'age' => [
        'filter' => FILTER_VALIDATE_INT,
        'options' => ['min_range' => 18, 'max_range' => 100]
    ],
    'website' => FILTER_VALIDATE_URL
];

$inputs = filter_input_array(INPUT_POST, $filters);

if ($inputs) {
    if ($inputs['username'] && $inputs['email'] && $inputs['age'] && $inputs['website']) {
        echo "모든 입력이 유효합니다.";
    } else {
        echo "입력 중 일부가 유효하지 않습니다.";
    }
} else {
    echo "입력 데이터를 필터링하는 데 실패했습니다.";
}
?>


8. 보안 고려사항

PHP 필터를 사용할 때는 보안을 강화하기 위해 다음 사항을 유의해야 합니다.

8.1 입력 데이터 검증

사용자 입력은 항상 검증하고 정화해야 합니다. 필터를 사용하여 데이터의 형식과 내용을 확인함으로써 SQL 인젝션, XSS 공격 등을 방지할 수 있습니다.

예시: XSS 방지

<?php
$input = "<script>alert('XSS');</script> Hello";

$sanitized = filter_var($input, FILTER_SANITIZE_SPECIAL_CHARS);
echo $sanitized; // 출력: &lt;script&gt;alert(&#039;XSS&#039;);&lt;/script&gt; Hello
?>

8.2 최소 권한 원칙 준수

필터를 사용할 때는 필요한 최소한의 필터만 적용하여 성능을 최적화하고, 불필요한 데이터 손실을 방지합니다.

8.3 오류 메시지 관리

필터링 과정에서 발생하는 오류는 사용자에게 구체적인 시스템 정보를 노출하지 않도록 주의해야 합니다. 오류 로그는 서버에 안전하게 기록하고, 사용자에게는 일반적인 오류 메시지만 표시합니다.

예시: 오류 로그 기록

<?php
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);

if (!$email) {
    error_log("유효하지 않은 이메일 주소: " . $_POST['email']);
    echo "입력한 이메일 주소가 유효하지 않습니다.";
}
?>

8.4 정규화된 경로 사용

파일 경로를 다룰 때는 realpath() 함수를 사용하여 경로를 정규화하고, 디렉토리 트래버설 공격을 방지합니다.

예시: 안전한 파일 접근

<?php
function sanitizePath($baseDir, $userInputPath) {
    $realBase = realpath($baseDir);
    $realUserPath = realpath($baseDir . DIRECTORY_SEPARATOR . $userInputPath);

    if ($realUserPath && strpos($realUserPath, $realBase) === 0) {
        return $realUserPath;
    } else {
        return false;
    }
}

$baseDir = "/var/www/html/uploads";
$userInput = $_GET['file'];

$sanitizedPath = sanitizePath($baseDir, $userInput);

if ($sanitizedPath) {
    if (file_exists($sanitizedPath)) {
        echo "파일을 찾았습니다: " . htmlspecialchars($sanitizedPath);
    } else {
        echo "파일이 존재하지 않습니다.";
    }
} else {
    echo "유효하지 않은 파일 경로입니다.";
}
?>

설명:

  • sanitizePath() 함수는 사용자 입력 경로를 기본 디렉토리와 결합한 후, 실제 절대 경로를 확인하여 기본 디렉토리 내부에 있는지 검증합니다.
  • 이를 통해 ../../ 같은 상대 경로를 통한 디렉토리 트래버설 공격을 방지할 수 있습니다.

9. 참조 자료


10. 요약

PHP 필터 참조는 사용자 입력 데이터를 효과적으로 검증하고 정화하는 데 필수적인 도구를 제공합니다. filter_var(), filter_input(), filter_var_array(), filter_input_array() 등의 함수를 활용하여 다양한 데이터 검증과 정화를 수행할 수 있습니다. 필터의 다양한 옵션과 플래그를 통해 필터의 동작을 세밀하게 제어할 수 있으며, 사용자 정의 필터를 통해 복잡한 데이터 처리 요구사항도 충족할 수 있습니다.

보안을 강화하기 위해 입력 데이터를 철저히 검증하고 정화하며, 최소 권한 원칙을 준수하고, 오류 메시지를 안전하게 관리하는 것이 중요합니다. PHP 필터를 잘 활용하면 웹 애플리케이션의 데이터 무결성과 보안성을 크게 향상시킬 수 있습니다.


: PHP 필터의 다양한 기능을 깊이 이해하고, 실용적인 예제를 통해 직접 구현해보는 것이 중요합니다. 이를 통해 실제 개발 환경에서 발생할 수 있는 다양한 데이터 처리 요구사항을 효과적으로 해결할 수 있는 능력을 키울 수 있습니다.


copyright ⓒ 스타트코딩 all rights reserved.
이메일 : startcodingim@gamil.com