Autenticação HTTP com PHP

Pode-se utilizar a função header() para enviar uma mensagem de "Authentication Required" para o navegador cliente, causando o aparecimento de uma janela para a entrada de Nome de Usuário/Senha. Uma vez que o usuário preencha um nome de usuário e uma senha, a URL contendo o script PHP será chamada mais uma vez com as variáveis predefinidas PHP_AUTH_USER, PHP_AUTH_PW, e AUTH_TYPE para determinar o nome de usuário, senha e tipo da autenticação, respectivamente. Estas variáveis predefinidas são encontradas no array $_SERVER. Somente o métodos de autenticação "Basic" é suportado. Consulte a função header() para mais informação.

Um exemplo de fragmento de script que forçaria a autenticação do cliente em uma página:

Example #1 Exemplo de Autenticação HTTP "Basic"

<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Texto enviado caso o usuário clique no botão Cancelar';
    exit;
} else {
    echo "<p>Olá, {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo "<p>Você digitou {$_SERVER['PHP_AUTH_PW']} como sua senha.</p>";
}
?>

Note: Nota sobre compatibilidade

Por favor, seja cauteloso ao codificar as linhas do cabeçalho HTTP. Para garantir máxima compatibilidade com todos os clientes, a palavra-chave "Basic" deve ser escrita com um "B" maiúsculo, a string realm deve ser envolvida por aspas duplas (nunca por aspas simples), e apenas um espaço deve preceder o código 401 na linha do cabeçalho HTTP/1.0 401. Parâmetros de autenticação precisam ser separados por vírgula.

Ao invés de simplesmente exibir PHP_AUTH_USER e PHP_AUTH_PW, como no exemplo acima, talvez queira verificar a validade do nome de usuário e senha. Talvez enviando uma consulta a um banco de dados, ou procurando o usuário em um arquivo dbm.

Cuidado com navegadores Internet Explorer bugados por aí. Eles parecem muito minuciosos sobre a ordem dos cabeçalhos. Enviar o cabeçalho WWW-Authenticate antes do cabeçalho HTTP/1.0 401 parece resolver isso por enquanto.

Note: Nota de configuração

PHP usa uma diretiva chamada AuthType para determinar se a autenticação externa está em efeito.

Perceba, entretanto, que a diretiva citada acima não previne que alguém que controle uma URL não autenticada roube senhas de URLs autenticadas no mesmo servidor.

Tanto o Netscape Navigator quanto o Internet Explorer apagarão o cache de autenticação da janela local do navegador para o realm após receber uma resposta 401 do servidor. Isso pode efetivamente "deslogar" um usuário, forçando o mesmo a re-entrar seu nome de usuário e senha. Algumas pessoas usam isso para delimitar o tempo de um login, ou prover um botão de "log-out".

Example #2 Exemplo de Autenticação HTTP forçando um novo nome/senha

<?php
function authenticate() {
    header('WWW-Authenticate: Basic realm="Test Authentication System"');
    header('HTTP/1.0 401 Unauthorized');
    echo "Você deve digitar um login e senha válidos para acessar este recurso\n";
    exit;
}

if (!isset($_SERVER['PHP_AUTH_USER']) ||
    ($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
    authenticate();
} else {
    echo "<p>Bem-vindo: " . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "<br />";
    echo "Antigo: " . 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-autenticar' />\n";
    echo "</form></p>\n";
}
?>

Este comportamento não é requerido pelo padrão de autenticação HTTP Basic, então nunca se deve depender dele. Testes com Lynx tem mostrado que Lynx não apaga as credenciais de autenticação com uma resposta 401 do servidor, assim, ao pressionar "Voltar" e então "Ir" novamente abrirá o recurso contanto que os requerimento de credenciais não tenha mudado. Contudo, o usuário pode pressionar a tecla '_' para apagar suas informações de autenticação.

Para fazer com que a autenticação HTTP funcione utilizando um servidor IIS com a versão CGI do PHP é necessário editar a configuração "Directory Security" do IIS. Clique em "Edit" e marque somente "Anonymous Access", deixe todos os outros campos desmarcados.

Note: Nota sobre IIS:
Para que a autenticação HTTP funcione com IIS, a diretiva do PHP cgi.rfc2616_headers deve ser definida como 0 (o valor default).