| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.openid.consumer">
- <title>Zend_OpenId_Consumer Grundlagen</title>
- <para>
- <classname>Zend_OpenId_Consumer</classname> kann verwendet werden um OpenID
- Authentifizierung auf Webseiten zu implementieren.
- </para>
- <sect2 id="zend.openid.consumer.authentication">
- <title>OpenID Authentifikation</title>
- <para>
- Aus der Sicht eines Website Entwicklers, geschieht die Authentifikation von OpenID in
- drei Schritten:
- </para>
- <orderedlist>
- <listitem>
- <para>Zeige das OpenID Authentifikations Formular</para>
- </listitem>
- <listitem>
- <para>Akzeptiere die OpenID Identität und übergib Sie an den OpenID Provider</para>
- </listitem>
- <listitem>
- <para>Überprüfe die Antwort des OpenID Providers</para>
- </listitem>
- </orderedlist>
- <para>
- Das OpenID Authentifikations Protokoll benötigt aktuell mehrere, aber viele von Ihnen
- sind innerhalb von <classname>Zend_OpenId_Consumer</classname> gekapselt, und deshalb
- für den Entwickler transparent.
- </para>
- <para>
- Der End-Benutzer initiiert den OpenID Authentifikations Prozess indem er Seine oder Ihre
- Identifikations Daten in der entsprechenden Form übermittelt. Das folgende Beispiel
- zeigt ein einfaches Formular das einen OpenID Identifikator akzeptiert. Es gilt zu
- beachten dass das Beispiel nur einen Login demonstriert.
- </para>
- <example id="zend.openid.consumer.example-1">
- <title>Das einfache OpenID Login Formular</title>
- <programlisting language="php"><![CDATA[
- <html><body>
- <form method="post" action="example-1_2.php"><fieldset>
- <legend>OpenID Login</legend>
- <input type="text" name="openid_identifier">
- <input type="submit" name="openid_action" value="login">
- </fieldset></form></body></html>
- ]]></programlisting>
- </example>
- <para>
- Dieses Formular übergibt bei der Übertragung eine OpenID Identität an das folgende
- <acronym>PHP</acronym> Skript welches den zweiten Schritt der Authentifizierung
- durchführt. Das <acronym>PHP</acronym> Skript muss in diesem Schritt nur die
- <methodname>Zend_OpenId_Consumer::login()</methodname> Methode aufrufen. Das erste
- Argument dieser Methode akzeptiert eine OpenID Identität, und das zweite ist die
- <acronym>URL</acronym> des Skripts das den dritten und letzten Schritt der
- Authentifizierung behandelt.
- </para>
- <example id="zend.openid.consumer.example-1_2">
- <title>Der Authentifizierungs Anfrage Handler</title>
- <programlisting language="php"><![CDATA[
- $consumer = new Zend_OpenId_Consumer();
- if (!$consumer->login($_POST['openid_identifier'], 'example-1_3.php')) {
- die("OpenID Login fehlgeschlagen.");
- }
- ]]></programlisting>
- </example>
- <para>
- Die <methodname>Zend_OpenId_Consumer::login()</methodname> Methode führt eine Suche nach
- einem gegebenen Identifikator durch und findet, bei Erfolg, die Adresse des Identitäts
- Providers und dessen Lokalen Idenzifizierer durch. Dann erstellt es eine Assoziation zum
- gegebenen Provider sodas beide, die Site und der Provider, um das gleiche Geheimnis
- teilen das verwendet wird um nachfolgende Nachrichten zu verschlüsseln. Letztendlich
- wird eine Authentifikations Anfrage an den Provider übergeben. Diese Anfrage leitet den
- Web-Browser des End-Benutzers zu einer OpenID Server Site um, wo der Benutzer die
- Möglichkeit habt den Authentifizierungs Prozess fortzuführen.
- </para>
- <para>
- Ein OpenID Provider fragt nochmalerweise Benutzer nach Ihrem Passwort (wenn Sie vorher
- noch nicht angemeldet waren), wenn der Benutzer dieser Site vertraut und welche
- Informationen zu der Site zurückgegeben werden können. Diese Interaktionen sind für den
- OpenID Konsument nicht sichtbar sodas es für Ihn keine Möglichkeit gibt das
- Benutzerpasswort oder andere Informationen zu bekommen bei denen der Benutzer nicht
- gesagt hat das der OpenId Provider Sie teilen darf.
- </para>
- <para>
- Bei Erfolg wird <methodname>Zend_OpenId_Consumer::login()</methodname> nicht
- zurückkommen, sondern eine <acronym>HTTP</acronym> Umleitung durchführt. Trotzdem wird
- im Falle eine Fehler ein <constant>FALSE</constant> zurückgeben wird. Fehler können
- durch eine ungültige Identität, einen Provider der nicht antwortet, Kommunikations
- Fehler, usw. auftreten.
- </para>
- <para>
- Der dritte Schritt der Authentifikation wird durch die Antwort vom OpenID Provider
- initiiert, nachdem dieser das Benutzerpasswort authentifiziert hat. Diese Antwort wird
- indirekt, als <acronym>HTTP</acronym> Umleitung übergeben, indem der Webbrowsers des
- End-Benutzers verwendet wird. Der Konsument muß nun einfach prüfen ob die Antwort gültig
- ist.
- </para>
- <example id="zend.openid.consumer.example-1_3">
- <title>Der Authentifizierungs Antwort Prüfer</title>
- <programlisting language="php"><![CDATA[
- $consumer = new Zend_OpenId_Consumer();
- if ($consumer->verify($_GET, $id)) {
- echo "GÜLTIG ". htmlspecialchars($id);
- } else {
- echo "UNGÜLTIG" . htmlspecialchars($id);
- }
- ]]></programlisting>
- </example>
- <para>
- Diese Prüfung wird durchgeführt indem die
- <classname>Zend_OpenId_Consumer::verify</classname> Methode verwendet wird, welche ein
- ganzes Array von HTTP Anfrage Argumenten entgegennimmt und prüft ob diese Antwort durch
- den OpenID Provider richtig signiert wurde. Sie kann die erhaltete OpenID Identität, die
- vom Endbenutzer im ersten Schritt angegeben wurde, zuordnen, indem ein zweites,
- optionales, Argument eingegeben wird.
- </para>
- </sect2>
- <sect2 id="zend.openid.consumer.combine">
- <title>Alle Schritte in einer Seite kombinieren</title>
- <para>
- Das folgende Beispiel kombiniert alle drei Schritte in einem Skript. Es bietet keine
- neuen Funktionalitäten. Der Vorteil der Verwendung eines einzelnen Skripts ist, das
- Entwickler keine <acronym>URL</acronym>'s für das Skript definieren muss, das den
- nächsten Schritt durchführt. Standardmäßig verwenden alle Schritte die gleiche
- <acronym>URL</acronym>. Trotzdem enthält das Skript nun etwas Dispatchcode um den
- korrekten Code für jeden Schritt der Authentifikation aufzurufen.
- </para>
- <example id="zend.openid.consumer.example-2">
- <title>Das komplette Skript für ein OpenID Login</title>
- <programlisting language="php"><![CDATA[
- $status = "";
- if (isset($_POST['openid_action']) &&
- $_POST['openid_action'] == "login" &&
- !empty($_POST['openid_identifier'])) {
- $consumer = new Zend_OpenId_Consumer();
- if (!$consumer->login($_POST['openid_identifier'])) {
- $status = "OpenID Login fehlgeschlagen.";
- }
- } else if (isset($_GET['openid_mode'])) {
- if ($_GET['openid_mode'] == "id_res") {
- $consumer = new Zend_OpenId_Consumer();
- if ($consumer->verify($_GET, $id)) {
- $status = "GÜLTIG " . htmlspecialchars($id);
- } else {
- $status = "UNGÜLTIG " . htmlspecialchars($id);
- }
- } else if ($_GET['openid_mode'] == "cancel") {
- $status = "ABGEBROCHEN";
- }
- }
- ?>
- <html><body>
- <?php echo "$status<br>" ?>
- <form method="post">
- <fieldset>
- <legend>OpenID Login</legend>
- <input type="text" name="openid_identifier" value=""/>
- <input type="submit" name="openid_action" value="login"/>
- </fieldset>
- </form>
- </body></html>
- ]]></programlisting>
- </example>
- <para>
- Zusätzlich unterscheidet dieser Code zwischen abgebrochen und ungültigen
- Authentifizierungs Antworten. Der Provider gibt eine abgebrochene Antwort zurück, wenn
- der Identitäts Provider die gegebene Identität nicht unterstützt, der Benutzer nicht
- angemeldet ist, oder der Benutzer der Seite nicht vertraut. Eine ungültige Antwort zeigt
- an das die Antwort dem OpenId Protokoll nicht entspricht oder nicht korrekt signiert
- wurde.
- </para>
- </sect2>
- <sect2 id="zend.openid.consumer.realm">
- <title>Konsumenten Bereiche</title>
- <para>
- Wenn eine OpenID-aktivierte Site eine Authentifikations Anfrage an einen Provider
- übergibt, identifiziert diese sich selbst mit einer Bereichs <acronym>URL</acronym>.
- Diese <acronym>URL</acronym> kann als Root der vertrauten Site betrachtet werden. Wenn
- der Benutzer der Bereichs <acronym>URL</acronym> vertraut, dann sollte er oder Sie das
- auch bei der passenden und den untergeordneten <acronym>URL</acronym>s tun.
- </para>
- <para>
- Standardmäßig wird die Bereichs <acronym>URL</acronym> automatisch auf die
- <acronym>URL</acronym> des Verzeichnisses gesetzt indem das Login Skript ist. Dieser
- Standardwert ist für die meisten, aber nicht alle, Fälle ausreichend. Manchmal sollte
- einer komplette Domain, und nicht einem Verzeichnis vertraut werden. Oder sogar einer
- Kombination von verschiedenen Servern in einer Domain.
- </para>
- <para>
- Um den Standardwert zu überschreiben müssen Entwickler die Bereichs
- <acronym>URL</acronym> als drittes Argument an die
- <classname>Zend_OpenId_Consumer::login</classname> Methode übergeben. Im folgenden
- Beispiel fragt eine einzelne Interaktion nach vertrauten Zugriff auf alle php.net Sites.
- </para>
- <example id="zend.openid.consumer.example-3_2">
- <title>Authentifizierungs Anfrage für spezielle Bereiche</title>
- <programlisting language="php"><![CDATA[
- $consumer = new Zend_OpenId_Consumer();
- if (!$consumer->login($_POST['openid_identifier'],
- 'example-3_3.php',
- 'http://*.php.net/')) {
- die("OpenID Login fehlgeschlagen.");
- }
- ]]></programlisting>
- </example>
- <para>
- Dieses Beispiel implementiert nur den zweiten Schritt der Authentifikation; der erste
- und dritte Schritt sind die identisch mit dem ersten Beispiel.
- </para>
- </sect2>
- <sect2 id="zend.openid.consumer.check">
- <title>Sofortige Prüfung</title>
- <para>
- In einigen Fällen muß eine Anwendung nur prüfen ob ein Benutzer bereits auf einem
- vertrauten OpenID Server eingeloggt ist ohne einer Interaktion mit dem Benutzer. Die
- <classname>Zend_OpenId_Consumer::check</classname> Methode führt genau das durch. Sie
- wird mit den gleichen Argumenten wie <classname>Zend_OpenId_Consumer::login</classname>
- ausgeführt, aber Sie zeigt dem Benutzer keine OpenID Serverseiten. Aus Sicht des
- Benutzers ist dieser Prozess transparent, und es scheint als ob er die Site nie
- verlässt. Der dritte Schritt ist erfolgreich wenn der Benutzer bereits angemeldet ist
- und der Site vertraut, andernfalls ist er erfolglos.
- </para>
- <example id="zend.openid.consumer.example-4">
- <title>Sofortige Prüfung ohne Interaktion</title>
- <programlisting language="php"><![CDATA[
- $consumer = new Zend_OpenId_Consumer();
- if (!$consumer->check($_POST['openid_identifier'], 'example-4_3.php')) {
- die("OpenID Login fehlgeschlaten.");
- }
- ]]></programlisting>
- </example>
- <para>
- Das Beispiel implementiert nur den zweiten Schritt der Authentifikation; der erste und
- dritte Schritt sind dem obigen Beispiel ähnlich.
- </para>
- </sect2>
- <sect2 id="zend.openid.consumer.storage">
- <title>Zend_OpenId_Consumer_Storage</title>
- <para>
- Es gibt drei Schritte beim Authentifizierungs Prozess von OpenID, und jeder wird durch
- eine separate <acronym>HTTP</acronym> Anfrage durchgeführt. Um die Informationen
- zwischen den Anfragen zu speichern verwendet <classname>Zend_OpenId_Consumer</classname>
- einen internen Speicher.
- </para>
- <para>
- Entwickler müssen sich nicht notwendigerweise um die Speicherung kümmern weil
- <classname>Zend_OpenId_Consumer</classname> standardmäßig einen dateibasierten Speicher
- im temporären Verzeichnis verwendet, ähnlich wie <acronym>PHP</acronym> Sessions.
- Trotzdem ist dieser Speicher nicht in allen Situationen richtig. Einige Entwickler
- wollen Informationen in einer Datenbank speichern, während andere einen üblichen Speicher
- für große Server-Farmen verwenden wollen. Glücklicherweise können Entwickler den
- Standardspeicher sehr einfach mit Ihrem eigenen tauschen. Um einen eigenen
- Speichermechanismus zu spezifizieren muß nur die
- <classname>Zend_OpenId_Consumer_Storage</classname> Klasse erweitert werden und diese
- Unterklasse dem <classname>Zend_OpenId_Consumer</classname> Konstruktor im ersten
- Argument übergeben werden.
- </para>
- <para>
- Das folgende Beispiel demonstriert einen einfachen Speicher Mechanismus der
- <classname>Zend_Db</classname> als sein Backend verwendet und drei Gruppen von
- Funktionen bereitstellt. Der erste Gruppe enthält Funktionen für die Arbeit mit
- Assoziationen, während die zweite Gruppe erkannte Informationen cacht, und die dritte
- Gruppe kann verwendet werden um zu prüfen ob die Antwort eindeutig ist. Die Klasse kann
- einfach mit bestehenden oder neuen Datenbanken verwendet werden; wenn die benötigten
- Tabellen nicht existieren, wird er Sie erstellen.
- </para>
- <example id="zend.openid.consumer.example-5">
- <title>Datenbank Speicher</title>
- <programlisting language="php"><![CDATA[
- class DbStorage extends Zend_OpenId_Consumer_Storage
- {
- private $_db;
- private $_association_table;
- private $_discovery_table;
- private $_nonce_table;
- // Übergib das Zend_Db_Adapter Objekt und die Namen der
- // benötigten Tabellen
- public function __construct($db,
- $association_table = "association",
- $discovery_table = "discovery",
- $nonce_table = "nonce")
- {
- $this->_db = $db;
- $this->_association_table = $association_table;
- $this->_discovery_table = $discovery_table;
- $this->_nonce_table = $nonce_table;
- $tables = $this->_db->listTables();
- // Erstelle die Assoziationstabellen wenn Sie nicht existieren
- if (!in_array($association_table, $tables)) {
- $this->_db->getConnection()->exec(
- "create table $association_table (" .
- " url varchar(256) not null primary key," .
- " handle varchar(256) not null," .
- " macFunc char(16) not null," .
- " secret varchar(256) not null," .
- " expires timestamp" .
- ")");
- }
- // Erstelle die Discoverytabellen wenn Sie nicht existieren
- if (!in_array($discovery_table, $tables)) {
- $this->_db->getConnection()->exec(
- "create table $discovery_table (" .
- " id varchar(256) not null primary key," .
- " realId varchar(256) not null," .
- " server varchar(256) not null," .
- " version float," .
- " expires timestamp" .
- ")");
- }
- // Erstelle die Nouncetabellen wenn Sie nicht existieren
- if (!in_array($nonce_table, $tables)) {
- $this->_db->getConnection()->exec(
- "create table $nonce_table (" .
- " nonce varchar(256) not null primary key," .
- " created timestamp default current_timestamp" .
- ")");
- }
- }
- public function addAssociation($url,
- $handle,
- $macFunc,
- $secret,
- $expires)
- {
- $table = $this->_association_table;
- $secret = base64_encode($secret);
- $this->_db->insert($table, array(
- 'url' => $url,
- 'handle' => $handle,
- 'macFunc' => $macFunc,
- 'secret' => $secret,
- 'expires' => $expires,
- ));
- return true;
- }
- public function getAssociation($url,
- &$handle,
- &$macFunc,
- &$secret,
- &$expires)
- {
- $table = $this->_association_table;
- $this->_db->delete(
- $table, $this->_db->quoteInto('expires < ?', time())
- );
- $select = $this-_db->select()
- ->from($table, array('handle', 'macFunc', 'secret', 'expires'))
- ->where('url = ?', $url);
- $res = $this->_db->fetchRow($select);
- if (is_array($res)) {
- $handle = $res['handle'];
- $macFunc = $res['macFunc'];
- $secret = base64_decode($res['secret']);
- $expires = $res['expires'];
- return true;
- }
- return false;
- }
- public function getAssociationByHandle($handle,
- &$url,
- &$macFunc,
- &$secret,
- &$expires)
- {
- $table = $this->_association_table;
- $this->_db->delete(
- $table, $this->_db->quoteInto('expires < ', time())
- );
- $select = $this->_db->select()
- ->from($table, array('url', 'macFunc', 'secret', 'expires')
- ->where('handle = ?', $handle);
- $res = $select->fetchRow($select);
- if (is_array($res)) {
- $url = $res['url'];
- $macFunc = $res['macFunc'];
- $secret = base64_decode($res['secret']);
- $expires = $res['expires'];
- return true;
- }
- return false;
- }
- public function delAssociation($url)
- {
- $table = $this->_association_table;
- $this->_db->query("delete from $table where url = '$url'");
- return true;
- }
- public function addDiscoveryInfo($id,
- $realId,
- $server,
- $version,
- $expires)
- {
- $table = $this->_discovery_table;
- $this->_db->insert($table, array(
- 'id' => $id,
- 'realId' => $realId,
- 'server' => $server,
- 'version' => $version,
- 'expires' => $expires,
- ));
- return true;
- }
- public function getDiscoveryInfo($id,
- &$realId,
- &$server,
- &$version,
- &$expires)
- {
- $table = $this->_discovery_table;
- $this->_db->delete($table, $this->quoteInto('expires < ?', time()));
- $select = $this->_db->select()
- ->from($table, array('realId', 'server', 'version', 'expires'))
- ->where('id = ?', $id);
- $res = $this->_db->fetchRow($select);
- if (is_array($res)) {
- $realId = $res['realId'];
- $server = $res['server'];
- $version = $res['version'];
- $expires = $res['expires'];
- return true;
- }
- return false;
- }
- public function delDiscoveryInfo($id)
- {
- $table = $this->_discovery_table;
- $this->_db->delete($table, $this->_db->quoteInto('id = ?', $id));
- return true;
- }
- public function isUniqueNonce($nonce)
- {
- $table = $this->_nonce_table;
- try {
- $ret = $this->_db->insert($table, array(
- 'nonce' => $nonce,
- ));
- } catch (Zend_Db_Statement_Exception $e) {
- return false;
- }
- return true;
- }
- public function purgeNonces($date=null)
- {
- }
- }
- $db = Zend_Db::factory('Pdo_Sqlite',
- array('dbname'=>'/tmp/openid_consumer.db'));
- $storage = new DbStorage($db);
- $consumer = new Zend_OpenId_Consumer($storage);
- ]]></programlisting>
- </example>
- <para>
- Dieses Beispiel zeigt keinen OpenID Authentifikations Code, aber dieser Code würde der
- gleiche sein wie der für die anderen Beispiel in diesem Kapitel.
- </para>
- </sect2>
- <sect2 id="zend.openid.consumer.sreg">
- <title>Einfache Registrations Erweiterung</title>
- <para>
- Zusätzlich zur Authentifikation kann OpenID Standard für einen leichtgewichtigen
- Profiltausch verwendet werden, um Informationen über einen Benutzer über mehrere Sites
- hinweg portabel zu machen. Dieses Feature wird nicht durch die OpenID Authentifikations
- Spezifikation abgedeckt, aber vom OpenID Einfachen Registrierungs Erweiterungs Protokoll
- unterstützt. Dieses Protokoll erlaubt es OpenID-aktivierten Sites nach Informationen
- über End-Benutzern von OpenID Providers zu fragen. Diese Informationen können folgendes
- beinhalten:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>nickname</emphasis> - ein UTF-8 String den der End-Benutzer als
- Spitzname verwendet.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>email</emphasis> - die Email Adresse des Benutzers wie in Sektion
- 3.4.1 von RFC2822 spezifiziert.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>fullname</emphasis> - eine UTF-8 String Repräsentation des kompletten
- Namens des Benutzers.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>dob</emphasis> - das Geburtsdatum des Benutzers im Format
- 'YYYY-MM-DD'. Jeder Wert dessen Repräsentation weniger als die speifizierte
- Anzahl an Ziffern in diesem Format verwendet sollte mit Nullen aufgefüllt
- werden. In anderen Worten, die Länge dieses Wertes muß immer 10 sein. Wenn der
- Benutzer irgendeinen Teil dieses Wertes (z.B. Jahr, Monat oder Tag) nicht
- angeben will, dann muß dieser auf Null gesetzt werden. Wenn ein Benutzer zum
- Beispiel angeben will das sein Geburtsdatum in das Jahr 1980 fällt, aber nicht
- den Monat oder Tag angeben will, dann sollte der zurückgegebene Wert
- '1980-00-00' sein.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>gender</emphasis> - das Geschlecht des Benutzers: "M" für männlich,
- "F" für weiblich
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>postcode</emphasis> - ein UTF-8 String der dem Postleitzahl System des
- Landes des End-Benutzers entspricht
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>country</emphasis> - das Land des Wohnsitzes des Benutzers wie
- in ISO3166 spezifiziert
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>language</emphasis> - die bevorzugte Sprache des Benutzers wie in
- ISO639 spezifiziert
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>timezone</emphasis> - ein <acronym>ASCII</acronym> String von der
- Zeitzonen Datenbank. Zum Beispiel, "Europe/Paris" oder "America/Los_Angeles".
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Eine OpenID-aktivierte Web-Seite kann nach jeder beliebigen Kombination dieser Felder
- fragen. Sie kann auch einige Informationen strikt fordern und es Benutzern erlauben
- zusätzliche Informationen anzubieten oder zu verstecken. Das folgende Beispiel
- Instanziiert die <classname>Zend_OpenId_Extension_Sreg</classname> Klasse die einen
- <emphasis>nickname</emphasis> (Spitzname) benötigt und optional eine
- <emphasis>email</emphasis> (E-Mail) und einen <emphasis>fullname</emphasis>
- (vollständigen Namen) benötigt.
- </para>
- <example id="zend.openid.consumer.example-6_2">
- <title>Anfragen mit einer einfachen Registrations Erweiterung senden</title>
- <programlisting language="php"><![CDATA[
- $sreg = new Zend_OpenId_Extension_Sreg(array(
- 'nickname'=>true,
- 'email'=>false,
- 'fullname'=>false), null, 1.1);
- $consumer = new Zend_OpenId_Consumer();
- if (!$consumer->login($_POST['openid_identifier'],
- 'example-6_3.php',
- null,
- $sreg)) {
- die("OpenID Login fehlgeschlagen.");
- }
- ]]></programlisting>
- </example>
- <para>
- Wie man sieht akzeptiert der <classname>Zend_OpenId_Extension_Sreg</classname>
- Konstruktor ein Array von OpenId Feldern. Das Array hat den Namen der Felder als Indezes
- zu einem Flag das anzeigt ob das Feld benötigt wird oder nicht.
- <constant>TRUE</constant> bedeutet der Wert wird benötigt und <constant>FALSE</constant>
- bedeutet das Feld ist optional. Die Methode
- <classname>Zend_OpenId_Consumer::login</classname> akzeptiert eine Erweiterung oder ein
- Array von Erweiterungen als sein viertes Argument.
- </para>
- <para>
- Im dritten Schritt der Authentifikation sollte das
- <classname>Zend_OpenId_Extension_Sreg</classname> Objekt an
- <classname>Zend_OpenId_Consumer::verify</classname> übergeben werden. Anschließend wird
- die Methode <classname>Zend_OpenId_Extension_Sreg::getProperties</classname>, bei
- erfolgreicher Authentifizierung, ein assoziatives Array von benötigten Feldern
- zurückgeben.
- </para>
- <example id="zend.openid.consumer.example-6_3">
- <title>Antworten mit einer einfachen Registierungs Erweiterung prüfen</title>
- <programlisting language="php"><![CDATA[
- $sreg = new Zend_OpenId_Extension_Sreg(array(
- 'nickname'=>true,
- 'email'=>false,
- 'fullname'=>false), null, 1.1);
- $consumer = new Zend_OpenId_Consumer();
- if ($consumer->verify($_GET, $id, $sreg)) {
- echo "GÜLTIG " . htmlspecialchars($id) . "<br>\n";
- $data = $sreg->getProperties();
- if (isset($data['nickname'])) {
- echo "Spitzname: " . htmlspecialchars($data['nickname']) . "<br>\n";
- }
- if (isset($data['email'])) {
- echo "Email: " . htmlspecialchars($data['email']) . "<br>\n";
- }
- if (isset($data['fullname'])) {
- echo "Vollständiger Name: " . htmlspecialchars($data['fullname'])
- . "<br>\n";
- }
- } else {
- echo "UNGÜLTIG " . htmlspecialchars($id);
- }
- ]]></programlisting>
- </example>
- <para>
- Wenn das <classname>Zend_OpenId_Extension_Sreg</classname> Objekt ohne Argumente
- erstellt wurde, sollte der Benutzercode selbst das Vorhandensein der benötigten Daten
- prüfen. Trotzdem, wenn das Objekt mit der gleichen Liste an benötigten Feldern wie im
- zweiten Schritt erstellt wird, wird es automatisch die Existenz der benötigten Daten
- prüfen. In diesem Fall wird <classname>Zend_OpenId_Consumer::verify</classname>
- <constant>FALSE</constant> zurückgeben wenn irgendeines der benötigten Felder fehlt.
- </para>
- <para>
- <classname>Zend_OpenId_Extension_Sreg</classname> verwendet standardmäßig die Version
- 1.0 weil die Spezifikation der Version 1.1 noch nicht fertiggestellt wurde. Trotzdem
- unterstützen einige Bibliotheken die Version 1.0 nicht vollständig. Zum Beispiel
- benötigt www.myopenid.com einen SREG Namensraum in den Anfragen der nur in 1.1 vorhanden
- ist. Um mit so einem Server zu Arbeiten muß man die Version 1.1 explizit im
- <classname>Zend_OpenId_Extension_Sreg</classname> Konstruktor setzen.
- </para>
- <para>
- Das zweite Argument des <classname>Zend_OpenId_Extension_Sreg</classname> Konstruktors
- ist eine Policy <acronym>URL</acronym>, die dem Benutzer durch den Identitäts Provider
- zur Verfügung gestellt werden sollte.
- </para>
- </sect2>
- <sect2 id="zend.openid.consumer.auth">
- <title>Integration mit Zend_Auth</title>
- <para>
- Zend Framework bietet eine spezielle Klasse für die Unterstützung von Benutzer
- Authentifikation: <classname>Zend_Auth</classname>. Diese Klasse kann zusammen mit
- <classname>Zend_OpenId_Consumer</classname> verwendet werden. Das folgende Beispiel
- zeigt wie <classname>OpenIdAdapter</classname> das
- <classname>Zend_Auth_Adapter_Interface</classname> mit der
- <methodname>authenticate()</methodname> Methode implementiert. Diese führt eine
- Authentifikations Anfrage und Verifikation durch.
- </para>
- <para>
- Der große Unterschied zwischen diesem Adapter und dem bestehenden ist, das er mit zwei
- <acronym>HTTP</acronym> Anfragen arbeitet und einen Dispatch code enthält um den zweiten
- oder dritten Schritt der OpenID Authentifikation durchzuführen.
- </para>
- <example id="zend.openid.consumer.example-7">
- <title>Zend_Auth Adapter für OpenID</title>
- <programlisting language="php"><![CDATA[
- class OpenIdAdapter implements Zend_Auth_Adapter_Interface {
- private $_id = null;
- public function __construct($id = null) {
- $this->_id = $id;
- }
- public function authenticate() {
- $id = $this->_id;
- if (!empty($id)) {
- $consumer = new Zend_OpenId_Consumer();
- if (!$consumer->login($id)) {
- $ret = false;
- $msg = "Authentifizierung fehlgeschlagen.";
- }
- } else {
- $consumer = new Zend_OpenId_Consumer();
- if ($consumer->verify($_GET, $id)) {
- $ret = true;
- $msg = "Authentifizierung erfolgreich";
- } else {
- $ret = false;
- $msg = "Authentifizierung fehlgeschlagen";
- }
- }
- return new Zend_Auth_Result($ret, $id, array($msg));
- }
- }
- $status = "";
- $auth = Zend_Auth::getInstance();
- if ((isset($_POST['openid_action']) &&
- $_POST['openid_action'] == "login" &&
- !empty($_POST['openid_identifier'])) ||
- isset($_GET['openid_mode'])) {
- $adapter = new OpenIdAdapter(@$_POST['openid_identifier']);
- $result = $auth->authenticate($adapter);
- if ($result->isValid()) {
- Zend_OpenId::redirect(Zend_OpenId::selfURL());
- } else {
- $auth->clearIdentity();
- foreach ($result->getMessages() as $message) {
- $status .= "$message<br>\n";
- }
- }
- } else if ($auth->hasIdentity()) {
- if (isset($_POST['openid_action']) &&
- $_POST['openid_action'] == "logout") {
- $auth->clearIdentity();
- } else {
- $status = "Du bist angemeldet als " . $auth->getIdentity() . "<br>\n";
- }
- }
- ?>
- <html><body>
- <?php echo htmlspecialchars($status);?>
- <form method="post"><fieldset>
- <legend>OpenID Login</legend>
- <input type="text" name="openid_identifier" value="">
- <input type="submit" name="openid_action" value="login">
- <input type="submit" name="openid_action" value="logout">
- </fieldset></form></body></html>
- ]]></programlisting>
- </example>
- <para>
- Mit <classname>Zend_Auth</classname> wird die Identität des End-Benutzes in den Session
- Daten gespeichert. Sie kann mit <classname>Zend_Auth::hasIdentity</classname> und
- <classname>Zend_Auth::getIdentity</classname> geprüft werden.
- </para>
- </sect2>
- <sect2 id="zend.openid.consumer.mvc">
- <title>Integration mit Zend_Controller</title>
- <para>
- Zuletzt ein paar Worte über die Integration in Model-View-Controller Anwendungen: Solche
- Zend Framework Anwendungen werden implementiert durch Verwenden der
- <classname>Zend_Controller</classname> Klasse und Sie verwenden die
- <classname>Zend_Controller_Response_Http</classname> Klasse um <acronym>HTTP</acronym>
- Antworten vorzubereiten und an den Web Browser des Benutzers zurückzusenden.
- </para>
- <para>
- <classname>Zend_OpenId_Consumer</classname> bietet keine GUI Möglichkeiten aber es führt
- <acronym>HTTP</acronym> Umleitungen bei erflgreichen
- <classname>Zend_OpenId_Consumer::login</classname> und
- <classname>Zend_OpenId_Consumer::check</classname> durch. Diese Umleitungen könnten
- nicht richtig funktionieren, oder sogar überhaupt nicht, wenn einige Daten bereits an
- den Web Browser gesendet wurden. Um <acronym>HTTP</acronym> Umleitungen im
- <acronym>MVC</acronym> Code richtig durchzuführen sollte die echte
- <classname>Zend_Controller_Response_Http</classname> als letztes Argument an
- <classname>Zend_OpenId_Consumer::login</classname> oder
- <classname>Zend_OpenId_Consumer::check</classname> gesendet werden.
- </para>
- </sect2>
- </sect1>
|