cvs: phpdoc-ca /features http-auth.xml

[email protected] ("Eduard Capell Brufau") Sun, 28 Aug 2005 16:57:42 -0000
Newsgroups php.doc.ca
Message-ID <cvseduardcapell1125248262@cvsserver>
--eduardcapell1125248262
Content-Type: text/plain

eduardcapell		Sun Aug 28 12:57:42 2005 EDT

  Added files:                 
    /phpdoc-ca/features	http-auth.xml 
  Log:
  
  
--eduardcapell1125248262
Content-Type: text/plain
Content-Disposition: attachment; filename="eduardcapell-20050828125742.txt"


http://cvs.php.net/co.php/phpdoc-ca/features/http-auth.xml?r=1.1&p=1
Index: phpdoc-ca/features/http-auth.xml
+++ phpdoc-ca/features/http-auth.xml
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- $Revision: 1.1 $ -->
<!-- EN-Revision: 1.42 Maintainer: eduardcapell Status: ready -->


 <chapter id="features.http-auth">
  <title>Autenticació HTTP amb PHP</title>

  <simpara>
   Els serveis d'Autenticació <acronym>HTTP</acronym> en PHP només estan
   disponibles quan executem el PHP com un mòdul d'Apache, i, per tant, no està
   disponible en la versió CGI. En un script de PHP (executant-se com a mòdul
   d'Apache), és possible d'utilitzar la funció <function>header</function> per
   tal d'enviar un missatge "Autenticació Requerida" al navegador del client,
   fent que aparegui una finestra d'entrada d'Usuari/Contrassenya. Quan l'usuari
   ha introduït l'usuari i la contrassenya, es cridarà la URL que contè l'script
   PHP amb les <link linkend="reserved.variables">variables predefinides</link> 
   <varname>PHP_AUTH_USER</varname>, <varname>PHP_AUTH_PW</varname>, 
   i <varname>AUTH_TYPE</varname>, establertes amb els valors de l'usuari, la
   contrassenya, i el tipus d'autenticació, respectivament. Aquestes variables
   predefinides les podem trobar als vectors 
   <link linkend="reserved.variables.server">$_SERVER</link> i 
   <varname>$HTTP_SERVER_VARS</varname>. Se suporten els mètodes "Basic" i
   "Digest" (des de PHP 5.1.0). Vegeu la funció <function>header</function> 
   per a saber-ne més.
  </simpara>

  <note>
   <title>Nota de la versió de PHP</title>
   <para>
    <link linkend="language.variables.superglobals">Autoglobals</link>, 
    com ara <link linkend="reserved.variables.server">$_SERVER</link>, van
    començar a estar disponibles en PHP 
    <ulink url="&url.php.release4.1.0;">4.1.0</ulink>. 
    <varname>$HTTP_SERVER_VARS</varname> ha estat disponible des de PHP 3.
   </para>
  </note>

  <para>
   Un exemple de fragment de codi que forçaria el client a autenticar-se en una
   pàgina seria de la manera següent:
  </para>
  <para>
   <example>
    <title>Exemple d'Autenticació HTTP Bàsica</title>
    <programlisting role="php">
<![CDATA[
<?php
  if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="El Meu Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Text a enviar si usuari prem el botó Cancel·lar';
    exit;
  } else {
    echo "<p>Hola {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo "<p>Heu entrat {$_SERVER['PHP_AUTH_PW']} en la contrassenya.</p>";
  }
?>
]]>
    </programlisting>
   </example>
  </para>

  <para>
   <example>
    <title>Exemple d'Autenticació HTTP Digest</title>
    <para>
     Aquest exemple us mostra com s'implementaria una seqüència amb Autenticació
     HTTP Digest. Per més informació, llegiu-vos la 
     <ulink url="&url.rfc;2617">RFC 2617</ulink>.
    </para>
    <programlisting role="php">
<![CDATA[
<?php
$realm = 'Àrea restringida';

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


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

    die('Text a enviar si usuari prem botó Cancel·lar');
}

// analitzem la variable PHP_AUTH_DIGEST
preg_match('/username="(?P<username>.*)",\s*realm="(?P<realm>.*)",\s*nonce="(?P<nonce>.*)",\s*uri="(?P<uri>.*)",\s*response="(?P<response>.*)",\s*opaque="(?P<opaque>.*)",\s*qop=(?P<qop>.*),\s*nc=(?P<nc>.*),\s*cnonce="(?P<cnonce>.*)"/', $_SERVER['PHP_AUTH_DIGEST'], $digest);

if (!isset($users[$digest['username']]))
    die('Nom d\'usuari no vàlid!');


// generem la resposta vàlida
$A1 = md5($digest['username'] . ':' . $realm . ':' . $users[$digest['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$digest['uri']);
$valid_response = md5($A1.':'.$digest['nonce'].':'.$digest['nc'].':'.$digest['cnonce'].':'.$digest['qop'].':'.$A2);

if ($digest['response'] != $valid_response)
    die('Credencials Incorrectes!');

// ok, usuari & contrassenya correctes
echo 'Us heu identificat com a: ' . $digest['username'];

?>
]]>
    </programlisting>
   </example>
  </para>

  <note>
   <title>Nota de Compatibilitat</title>
   <para>
    Aneu amb molt de compte quan escriviu les línies de les capçaleres HTTP. Per
    tal de garantir la màxima compatibilitat amb tots els clients, la paraula
    clau "Basic" s'ha d'escriure amb una "B" (en majúscula), la cadena de text
    del "realm" ha d'estar entre cometes dobles (NO simples), i el codi
    <emphasis>401</emphasis> ha d'anar precedit d'exactament un espai en la
    línia de la capçalera <emphasis>HTTP/1.0 401</emphasis>.
   </para>
  </note>

  <para>
   Enlloc d'escriure els valors de <varname>PHP_AUTH_USER</varname>
   i <varname>PHP_AUTH_PW</varname>, tal com s'ha fet en l'exemple previ, potser
   voldreu comprovar l'usuari i password per veure si són correctes.
   Probablement enviant una consulta a una base de dades, o buscant l'usuari en
   un fitxer dbm.
  </para>

  <para>
   Aneu amb compte amb navegadors Internet Explorers "defectuosos". Algunes
   versions són molt sensibles a l'ordre de les capçaleres. Per ara, sembla que
   si s'envia la capçalera <emphasis>WWW-Authenticate</emphasis> abans de la 
   capçalera <literal>HTTP/1.0 401</literal> tot funciona correctament.
  </para>

  <simpara>
   Des de PHP 4.3.0, per tal de prevenir que algú escrigui una seqüència que
   reveli la contrassenya d'una pàgina que ha estat autenticada a través d'un
   mecanisme extern tradicional, les variables PHP_AUTH no estaran establertes
   si l'autenticació externa s'ha habilitat per aquella pàgina i &safemode; està
   habilitat. En qualsevol cas, es pot utiltizar <varname>REMOTE_USER</varname> 
   per a identificar l'usuari autenticat externament, utilitzant 
   <varname>$_SERVER['REMOTE_USER']</varname>.
  </simpara>

  <note>
   <title>Nota de Configuració</title>
   <para>
    PHP utilitza la presència d'una directiva <literal>AuthType</literal> per a
    determinar si l'autenticació externa està habilitada o no.
   </para>
  </note>

  <simpara>
   Observeu, però, que el que s'ha comentat anteriorment no evita que algú que
   controla una URL no autenticada pugui robar contrassenyes d'URLs autenticades
   en el mateix servidor.
  </simpara>
  <simpara>
   Tant el Netscape Navigator com l'Internet Explorer esborren la memòria cau
   d'autenticació del navegador local pel reialme, després de rebre una resposta
   401 des del servidor. Això força un "log-out" de l'usuari, obligant-lo a
   reintroduir el seu nom d'usuari i contrassenya. A vegades s'utilitza això per
   tal de simular "time-outs" o per proporcionar botons de "log-out".
  </simpara>
  <para>
   <example>
    <title>Exemple d'Autenticació HTTP forçant un nou 
    usuari/contrassenya</title>
    <programlisting role="php">
<![CDATA[
<?php
  function authenticate() {
    header('WWW-Authenticate: Basic realm="Sistema de Prova d\'Autenticació"');
    header('HTTP/1.0 401 Unauthorized');
    echo "Heu d\'entrar un nom d\'usuari i contrassenya vàlids per a accedir\n";
    exit;
  }
 
  if (!isset($_SERVER['PHP_AUTH_USER']) ||
      ($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
   authenticate();
  } 
  else {
   echo "<p>Benvingut: {$_SERVER['PHP_AUTH_USER']}<br />";
   echo "Antic: {$_REQUEST['OldAuth']}";
   echo "<form action='{$_SERVER['PHP_SELF']}' METHOD='post'>\n";
   echo "<input type='hidden' name='SeenBefore' value='1' />\n";
   echo "<input type='hidden' name='OldAuth' value='{$_SERVER['PHP_AUTH_USER']}' />\n";
   echo "<input type='submit' value='Re-Autenticar' />\n";
   echo "</form></p>\n";
  }
?>
]]>
    </programlisting>
   </example>
  </para>
  <simpara>
   Aquest comportament no el requereix l'estandard de l'autenticació Bàsica
   HTTP, i per tant no us n'heu de refiar. Hem fet proves amb el Lynx, i aquest
   no esborra les credencials d'autenticació quan rep una resposta 401, de
   manera que anant enrere i endavant amb els botons de navegació, s'obrirà el
   recurs protegit, mentre els requeriments de les credencials no hagin canviat.
   L'usuari pot, però, prémer la tecla '_' per tal d'esborrar la seva informació
   d'autenticació.
  </simpara>
  <simpara>
   Observeu també que fins a PHP 4.3.3, l'Autenticació HTTP no funcionava quan
   s'utilitzava el servidor Microsoft IIS amb la versió CGI de PHP, degut a una
   limitació de IIS. Per tal de fer que funcioni amb PHP 4.3.3+, heu d'editar la
   configuració del IIS, en "Seguretat de Directori". Feu click en "Edició", i
   marqueu tan sols "Accés Anònim", i deixeu la resta de camps sense marcar.
  </simpara>
  <simpara>
   Una altra limitació es dóna si esteu utilitzant el mòdul IIS (ISAPI) i PHP 4,
   ja que no podreu utilitzar les variables <literal>PHP_AUTH_*</literal>, sinó
   que haureu d'utilitzar <literal>HTTP_AUTHORIZATION</literal>. Per exemple, 
   com en el codi següent: <literal>list($user, $pw) = explode(':',
    base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));</literal>
  </simpara>
  <note>
   <title>Nota d'IIS:</title>
   <simpara>
    Per tal que l'Autenticació HTTP funcioni amb IIS, la directiva PHP 
    <link linkend="ini.cgi.rfc2616-headers">cgi.rfc2616_headers</link> s'ha 
    d'establir al valor <literal>0</literal> (el seu valor per defecte).
   </simpara>
  </note>
  <note>
   <para>
    Si està activat el <link linkend="ini.safe-mode">mode segur</link>, l'uid de
    l'script s'afegirà al <literal>reialme</literal>, en la part de la capçalera
    <literal>WWW-Authenticate</literal>.
   </para>
  </note>

 </chapter>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

--eduardcapell1125248262--