2010-07-16 11 views
6

Recientemente, he comenzado a escribir mi propia clase de usuarios de PHP OpenID para comprender mejor el uso de openID. Como guía, he estado haciendo referencia a [Clase LightOpenID] [1]. En general, entiendo el código y cómo funciona OpenID. Mi confusión viene cuando se mira en discover función del autor:Métodos de descubrimiento de OpenID - Yadis VS HTML

function discover($url) 
{ 
    if(!$url) throw new ErrorException('No identity supplied.'); 
    # We save the original url in case of Yadis discovery failure. 
    # It can happen when we'll be lead to an XRDS document 
    # which does not have any OpenID2 services. 
    $originalUrl = $url; 

    # A flag to disable yadis discovery in case of failure in headers. 
    $yadis = true; 

    # We'll jump a maximum of 5 times, to avoid endless redirections. 
    for($i = 0; $i < 5; $i ++) { 
     if($yadis) { 
      $headers = explode("\n",$this->request($url, 'HEAD')); 

      $next = false; 
      foreach($headers as $header) { 
       if(preg_match('#X-XRDS-Location\s*:\s*(.*)#', $header, $m)) { 
        $url = $this->build_url(parse_url($url), parse_url(trim($m[1]))); 
        $next = true; 
       } 

       if(preg_match('#Content-Type\s*:\s*application/xrds\+xml#i', $header)) { 
        # Found an XRDS document, now let's find the server, and optionally delegate. 
        $content = $this->request($url, 'GET'); 

        # OpenID 2 
        # We ignore it for MyOpenID, as it breaks sreg if using OpenID 2.0 
        $ns = preg_quote('http://specs.openid.net/auth/2.0/'); 
        if (preg_match('#<Service.*?>(.*)<Type>\s*'.$ns.'(.*?)\s*</Type>(.*)</Service>#s', $content, $m) 
         && !preg_match('/myopenid\.com/i', $this->identity)) { 
         $content = $m[1] . $m[3]; 
         if($m[2] == 'server') $this->identifier_select = true; 

         $content = preg_match('#<URI>(.*)</URI>#', $content, $server); 
         $content = preg_match('#<LocalID>(.*)</LocalID>#', $content, $delegate); 
         if(empty($server)) { 
          return false; 
         } 
         # Does the server advertise support for either AX or SREG? 
         $this->ax = preg_match('#<Type>http://openid.net/srv/ax/1.0</Type>#', $content); 
         $this->sreg = preg_match('#<Type>http://openid.net/sreg/1.0</Type>#', $content); 

         $server = $server[1]; 
         if(isset($delegate[1])) $this->identity = $delegate[1]; 
         $this->version = 2; 

         $this->server = $server; 
         return $server; 
        } 

        # OpenID 1.1 
        $ns = preg_quote('http://openid.net/signon/1.1'); 
        if(preg_match('#<Service.*?>(.*)<Type>\s*'.$ns.'\s*</Type>(.*)</Service>#s', $content, $m)) { 
         $content = $m[1] . $m[2]; 

         $content = preg_match('#<URI>(.*)</URI>#', $content, $server); 
         $content = preg_match('#<.*?Delegate>(.*)</.*?Delegate>#', $content, $delegate); 
         if(empty($server)) { 
          return false; 
         } 
         # AX can be used only with OpenID 2.0, so checking only SREG 
         $this->sreg = preg_match('#<Type>http://openid.net/sreg/1.0</Type>#', $content); 

         $server = $server[1]; 
         if(isset($delegate[1])) $this->identity = $delegate[1]; 
         $this->version = 1; 

         $this->server = $server; 
         return $server; 
        } 

        $next = true; 
        $yadis = false; 
        $url = $originalUrl; 
        $content = null; 
        break; 
       } 
      } 
      if($next) continue; 

      # There are no relevant information in headers, so we search the body. 
      $content = $this->request($url, 'GET'); 
      if($location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'value')) { 
       $url = $this->build_url(parse_url($url), parse_url($location)); 
       continue; 
      } 
     } 

     if(!$content) $content = $this->request($url, 'GET'); 

     # At this point, the YADIS Discovery has failed, so we'll switch 
     # to openid2 HTML discovery, then fallback to openid 1.1 discovery. 
     $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href'); 
     $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href'); 
     $this->version = 2; 

     # Another hack for myopenid.com... 
     if(preg_match('/myopenid\.com/i', $server)) { 
      $server = null; 
     } 

     if(!$server) { 
      # The same with openid 1.1 
      $server = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href'); 
      $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href'); 
      $this->version = 1; 
     } 

     if($server) { 
      # We found an OpenID2 OP Endpoint 
      if($delegate) { 
       # We have also found an OP-Local ID. 
       $this->identity = $delegate; 
      } 
      $this->server = $server; 
      return $server; 
     } 

     throw new ErrorException('No servers found!'); 
    } 
    throw new ErrorException('Endless redirection!'); 
} 


    [1]: http://gitorious.org/lightopenid 

Bueno, aquí está la lógica como lo entiendo (básicamente):

  1. Compruebe si el $url le envía un archivo XRDS válidos que a continuación, analiza para averiguar el punto final del proveedor de OpenID.
    • Desde mi entender, esto se conoce como el método de autenticación Yadis.
  2. Si no se encuentra ningún archivo XRDS, Compruebe el cuerpo de la respuesta para un enlace HTML < > etiqueta que contiene la dirección URL del punto final.

Qué. Los. Infierno.

Me refiero en serio? Básicamente, raspe la respuesta y espere encontrar un enlace con el valor de atributo apropiado.

Ahora, no me malinterpreten, esta clase funciona como un encanto y es increíble. Simplemente no logro asimilar los dos métodos separados que se usan para descubrir el punto final: XRDS (yadis) y HTML.

Mis preguntas

  1. Son aquellos los únicos dos métodos utilizados en el proceso de descubrimiento?
  2. ¿Se usa uno solo en la versión 1.1 de OpenID y el otro en la versión 2?
  3. ¿Es fundamental admitir ambos métodos?
  4. El sitio en el que me he encontrado con el método HTML es Yahoo. ¿Están locos?

Gracias de nuevo por su tiempo amigos. Me disculpo si sueno un poco atónito, pero estaba realmente aturdido con la metodología una vez que comencé a entender qué medidas se estaban tomando para encontrar el endPoint.

Respuesta

5

Specification es tu amigo.

Pero respondiendo a tu pregunta:

  1. Sí. Esos son los dos únicos métodos definidos por las especificaciones de OpenID (al menos para las URL: hay un tercer método para XRI).
  2. No, ambos se pueden usar con ambas versiones del protocolo. Lea la función con cuidado, y verá que es compatible con ambos métodos para ambas versiones.
  3. Si desea que su biblioteca funcione con todos los proveedores y usuarios, será mejor que lo haga. Algunos usuarios pegan las etiquetas HTML en sus sitios, por lo que la URL de su sitio se puede usar como un archivo abierto.
  4. Algunos proveedores incluso usan ambos métodos a la vez, para mantener la compatibilidad con los consumidores que no implementan el descubrimiento YADIS (que no es parte de OpenID 1.1, pero puede usarse con él). Entonces eso tiene sentido.

Y sí, el descubrimiento de HTML se trata de buscar <link> en el cuerpo de la respuesta. Es por eso que se llama descubrimiento HTML.

+0

Información excelente, explicación muy útil. Gracias por tomarse el tiempo para abordar mi confusión/frustración. +1 y la respuesta para arrancar. –