PHP로 HTTP 인증하기

header() 함수를 사용하여 "인증 요구" 메시지를 클라이언트 브라우저에 보내 사용자 이름/비밀번호 입력 창을 팝업할 수 있습니다. 사용자가 사용자 이름과 암호를 입력하면 PHP 스크립트가 포함된 URL이 미리 정의된 변수 PHP_AUTH_USER, PHP_AUTH_PW 및 AUTH_TYPE를 사용자 이름, 암호 및 인증 유형으로 각각 설정하여 다시 호출됩니다. 이러한 미리 정의된 변수는 $_SERVER 배열에서 찾을 수 있습니다. "Basic" 및 "Digest" 인증 방법만 지원됩니다. 자세한 내용은 header() 함수를 참조하세요.

다음은 페이지에 대해 클라이언트 인증을 강제하는 예제 스크립트입니다:

Example #1 Basic HTTP 인증 예제

                  
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
  header('WWW-Authenticate: Basic realm="My Realm"');
  header('HTTP/1.0 401 Unauthorized');
  echo '사용자가 취소 버튼을 눌렀을 때 전송되는 텍스트';
  exit;
} else {
  echo "<p>안녕하세요 {$_SERVER['PHP_AUTH_USER']}.</p>";
  echo "<p> {$_SERVER['PHP_AUTH_PW']} 를 패스워드로 접속했습니다.</p>";
}
?>
                  
                

Example #2 Digest HTTP 인증 예제

이 예에서는 간단한 Digest HTTP 인증 스크립트를 구현하는 방법을 보여줍니다. 자세한 내용은 » RFC 2617을 참조하세요.

                  
<?php
$realm = '제한 영역';

//user => password
$users = array('admin' => 'mypass', 'guest' => 'guest');


if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="'.$realm.
          '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');

    die('사용자가 취소 버튼을 눌렀을 때 보내지는 텍스트');
}


// PHP_AUTH_DIGEST 변수 조사
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
    !isset($users[$data['username']]))
    die('Wrong Credentials!');


// generate the valid response
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);

if ($data['response'] != $valid_response)
    die('Wrong Credentials!');

// ok, 유효한 username & password
echo  $data['username'] . 'ok, 유효한 username & password ' ;


// http auth 헤더를 처리하는 함수
function http_digest_parse($txt)
{
    // protect against missing data
    $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
    $data = array();
    $keys = implode('|', array_keys($needed_parts));

    preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);

    foreach ($matches as $m) {
        $data[$m[1]] = $m[3] ? $m[3] : $m[4];
        unset($needed_parts[$m[1]]);
    }

    return $needed_parts ? false : $data;
}
?>
                  
                
참고: 호환성 참고

HTTP 헤더 행을 코딩할 때 주의하십시오. 모든 클라이언트와의 최대 호환성을 보장하기 위해 키워드 "Basic"은 대문자 "B"로 작성되어야 하고 영역 문자열은 큰따옴표(작은 따옴표 아님)로 묶어야 하며 정확히 한 공백이 401 코드 앞에 있어야 합니다. HTTP/1.0 401 헤더 라인. 인증 매개변수는 위의 요약 예제에서 볼 수 있듯이 쉼표로 구분되어야 합니다.

버그가 있는 Internet Explorer 브라우저를 조심하세요. 그들은 헤더의 순서에 대해 매우 까다롭게 보입니다. HTTP/1.0 401 헤더보다 먼저 WWW-Authenticate 헤더를 보내는 것이 현재로서는 트릭을 수행하는 것 같습니다.

참고: 구성 참고

PHP는 AuthType 지시문을 사용하여 외부 인증이 유효한지 여부를 결정합니다.

그러나 위의 내용이 인증되지 않은 URL을 제어하는 ​​사람이 동일한 서버의 인증된 URL에서 비밀번호를 도용하는 것을 방지하지는 않습니다.

Netscape Navigator와 Internet Explorer는 모두 401의 서버 응답을 받으면 영역에 대한 로컬 브라우저 창의 인증 캐시를 지웁니다. 이렇게 하면 사용자가 효과적으로 "로그아웃"되어 사용자 이름과 암호를 다시 입력해야 할 수 있습니다. 어떤 사람들은 이것을 사용하여 로그인을 "시간 초과"하거나 "로그아웃" 버튼을 제공합니다.

Example #3 새 이름/패스워드를 강제하는 HTTP 인증 예제

                  
<?php
function authenticate() {
    header('WWW-Authenticate: Basic realm="Test Authentication System"');
    header('HTTP/1.0 401 Unauthorized');
    echo "You must enter a valid login ID and password to access this resource\n";
    exit;
}

if (!isset($_SERVER['PHP_AUTH_USER']) ||
    ($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
    authenticate();
} else {
    echo "<p>Welcome: " . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "<br />";
    echo "Old: " . htmlspecialchars($_REQUEST['OldAuth']);
    echo "<form action='' method='post'>\n";
    echo "<input type='hidden' name='SeenBefore' value='1' />\n";
    echo "<input type='hidden' name='OldAuth' value=\"" . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "\" />\n";
    echo "<input type='submit' value='Re Authenticate' />\n";
    echo "</form></p>\n";
}
?>
                  
                

이 동작은 HTTP 기본 인증 표준에서 필요하지 않으므로 이에 의존해서는 안 됩니다. Lynx로 테스트한 결과 Lynx는 401 서버 응답으로 인증 자격 증명을 지우지 않으므로 자격 증명 요구 사항이 변경되지 않는 한 뒤로 누른 다음 앞으로 다시 누르면 리소스가 열립니다. 그러나 사용자는 '_' 키를 눌러 인증 정보를 삭제할 수 있습니다.

CGI 버전의 PHP와 함께 IIS 서버를 사용하여 HTTP 인증이 작동하도록 하려면 IIS 구성 "디렉토리 보안"을 편집해야 합니다. "편집"을 클릭하고 "익명 액세스"만 선택하고 다른 모든 필드는 선택하지 않은 상태로 두어야 합니다.

참고: IIS 참고:

HTTP 인증이 IIS에서 작동하려면 PHP 지시문 cgi.rfc2616_headers를 0(기본값)으로 설정해야 합니다.