2010-07-16 10 views
6

Recentemente, ho iniziato a scrivere la mia classe di consumer OpenID PHP per comprendere meglio OpenID. Come guida, ho fatto riferimento alla [classe LightOpenID] [1]. Per la maggior parte, capisco il codice e come funziona OpenID. La mia confusione arriva quando guardando discover funzione dell'autore:- 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 

Ok, ecco la logica se ho capito bene (in pratica):

  1. Verificare se il $url si invia un file XRDS valide che quindi analizzare per capire l'endpoint del provider OpenID.
    • Dalla mia comprensione, questo è chiamato il metodo di autenticazione Yadis.
  2. Se non viene trovato alcun file XRDS, Controllare il corpo della risposta di un HTML <collegamento> tag che contiene l'URL dell'endpoint.

Cosa. Il. Heck.

Intendo seriamente? In sostanza, lo schermo racchiude la risposta e spero che trovi un collegamento con il valore dell'attributo appropriato?

Ora, non fraintendetemi, questa classe funziona come un fascino ed è fantastico. Non riesco a trovare i due metodi separati usati per scoprire l'endpoint: XRDS (yadis) e HTML.

Le mie domande

  1. sono quelli gli unici due metodi utilizzati nel processo di scoperta?
  2. Si utilizza solo nella versione 1.1 di OpenID e l'altra nella versione 2?
  3. È fondamentale supportare entrambi i metodi?
  4. Il sito in cui ho incontrato il metodo HTML è Yahoo. Sono matti?

Grazie ancora per il vostro tempo. Mi scuso se mi sembro un po 'sbalordito, ma sono stato sinceramente sbalordito dalla metodologia quando ho iniziato a capire quali misure venivano prese per trovare l'endpoint.

risposta

5

Specification è un tuo amico.

Ma rispondere alla tua domanda:

  1. Sì. Questi sono gli unici due metodi definiti dalle specifiche OpenID (almeno, per gli URL - esiste un terzo metodo per gli XRI).
  2. No, entrambi possono essere utilizzati con entrambe le versioni del protocollo. Leggi attentamente la funzione e vedrai che supporta entrambi i metodi per entrambe le versioni.
  3. Se vuoi che la tua libreria funzioni con ogni fornitore e utente, è meglio che tu faccia. Alcuni utenti incollano i tag HTML nei loro siti, quindi l'url del loro sito può essere usato come openid.
  4. Alcuni provider utilizzano entrambi i metodi contemporaneamente per mantenere la compatibilità con i consumatori che non implementano il rilevamento YADIS (che non fa parte di OpenID 1.1, ma può essere utilizzato con esso). Quindi ha senso.

E sì, la scoperta di HTML riguarda la ricerca di un <link> nel corpo della risposta. Ecco perché si chiama scoperta HTML.

+0

Informazioni eccellenti, spiegazione molto utile. Grazie per aver dedicato del tempo ad affrontare la mia confusione/frustrazione. +1 e la risposta per l'avvio. –