Zend_Auth_Adapter_DbTable.xml 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 15684 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.auth.adapter.dbtable">
  5. <title>Datenbanktabellen Authentifizierung</title>
  6. <sect2 id="zend.auth.adapter.dbtable.introduction">
  7. <title>Einführung</title>
  8. <para>
  9. <classname>Zend_Auth_Adapter_DbTable</classname> bietet die Möglichkeit sich gegenüber
  10. Zeugnissen zu authentifizieren die in einer Datenbank Tabelle gespeichert sind. Weil
  11. <classname>Zend_Auth_Adapter_DbTable</classname> eine Instanz von
  12. <classname>Zend_Db_Adapter_Abstract</classname> benötigt, die an den Konstruktor
  13. übergeben wird, ist jede Instanz an eine spezielle Datenbank Verbindung verknüpft.
  14. Andere Konfigurationsoptionen können durch den Konstruktor gesetzt werden und durch die
  15. Methoden der Instanz. Eine für jede Option.
  16. </para>
  17. <para>
  18. Die vorhandenen Konfigurationsoptionen beinhalten:
  19. <itemizedlist>
  20. <listitem>
  21. <para>
  22. <code>tableName</code>: Das ist der Name der Datenbanktabelle welche die
  23. Authentifikations Zeugnisse enthält, und gegen die die Datenbank
  24. Authentifikations Abfrage durchgeführt wird.
  25. </para>
  26. </listitem>
  27. <listitem>
  28. <para>
  29. <code>identityColumn</code>: Ist der Name der Spalte der Datenbanktabelle
  30. die die Identität repräsentiert. Die Spalte der Identität muß eindeutige und
  31. einmalige Werte enthalten, wie einen Benutzernamen oder eine Email Adresse.
  32. </para>
  33. </listitem>
  34. <listitem>
  35. <para>
  36. <code>credentialColumn</code>: Das ist der Name der Spalte der
  37. Datenbanktabelle die verwendet wird um die Zeugnisse zu repräsentieren. Bei
  38. einem einfachen Identitäts und Passwort-Authentifizierungs Schema
  39. korrespondieren die Zeugnisse mit dem Passwort. Siehe auch die
  40. <code>credentialTreatment</code> Option.
  41. </para>
  42. </listitem>
  43. <listitem>
  44. <para>
  45. <code>credentialTreatment</code>: In vielen Fällen sind Passwörter und
  46. andere sensitive Daten verschlüsselt, gehasht, kodiert, gesalted,
  47. verschleiert oder auf andere Weise durch irgendeine Funktion oder einen
  48. Algorithmus behandelt. Durch die Spezifikation eines parametrisierbaren
  49. Behandlungsstrings mit dieser Methode, wie <code>'MD5(?)'</code> oder
  50. <code>'PASSWORD(?)'</code>, könnte ein Entwickler beliebiges SQL an den
  51. Eingabe- Zeugnis-Daten anwenden. Da diese Funktionen der darunter liegenden
  52. RDBMS speziell gehören, sollte das Handbuch der Datenbank auf das
  53. Vorhandensein solcher Funktionen im eigenen Datenbank System geprüft werden.
  54. </para>
  55. </listitem>
  56. </itemizedlist>
  57. </para>
  58. <example id="zend.auth.adapter.dbtable.introduction.example.basic_usage">
  59. <title>Grundsätzliche Verwendung</title>
  60. <para>
  61. Wie bereits in der Einführung beschrieben benötigt der
  62. <classname>Zend_Auth_Adapter_DbTable</classname> Konstruktor eine Instanz von
  63. <classname>Zend_Db_Adapter_Abstract</classname> die als Datenbank Verbindung
  64. fungiert zu welcher die Instanz des Authentifizierungs-Adapters gebunden ist. Zuerst
  65. sollte die Datenbankverbindung erstellt werden.
  66. </para>
  67. <para>
  68. Der folgende Code erstellt eien Adapter für eine In-Memory Datenbank, erstellt ein
  69. einfaches Datenbankschema, und fügt eine Zeile ein gegen die später eine
  70. Authentifizierungs-Abfrage durchgeführt werden kann. Dieses Beispiel benötigt die
  71. SQLite Erweiterung:
  72. </para>
  73. <programlisting language="php"><![CDATA[
  74. // Erstellt eine In-Memory SQLite Datenbankverbindung
  75. $dbAdapter = new Zend_Db_Adapter_Pdo_Sqlite(array('dbname' =>
  76. ':memory:'));
  77. // Erstellt eine einfache Datenbank-Erstellungs-Abfrage
  78. $sqlCreate = 'CREATE TABLE [users] ('
  79. . '[id] INTEGER NOT NULL PRIMARY KEY, '
  80. . '[username] VARCHAR(50) UNIQUE NOT NULL, '
  81. . '[password] VARCHAR(32) NULL, '
  82. . '[real_name] VARCHAR(150) NULL)';
  83. // Erstellt die Tabelle für die Authentifizierungs Zeugnisse
  84. $dbAdapter->query($sqlCreate);
  85. // Erstellt eine Abfrage um eine Zeile einzufügen für die eine
  86. // Authentifizierung erfolgreich sein kann
  87. $sqlInsert = "INSERT INTO users (username, password, real_name) "
  88. . "VALUES ('my_username', 'my_password', 'My Real Name')";
  89. // Daten einfügen
  90. $dbAdapter->query($sqlInsert);
  91. ]]></programlisting>
  92. <para>
  93. Mit der Datenbankverbindung und den vorhandenen Tabellendaten, kann eine Instanz von
  94. <classname>Zend_Auth_Adapter_DbTable</classname> erstellt werden. Die Werte der
  95. Konfigurationsoptionen können dem Konstruktor übergeben werden, oder als Parameter
  96. der setzenden Methoden nach der Instanziierung:
  97. </para>
  98. <programlisting language="php"><![CDATA[
  99. // Die Instanz mit Konstruktor Parametern konfiurieren...
  100. $authAdapter = new Zend_Auth_Adapter_DbTable(
  101. $dbAdapter,
  102. 'users',
  103. 'username',
  104. 'password'
  105. );
  106. // ...oder die Instanz mit den setzenden Methoden konfigurieren
  107. $authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
  108. $authAdapter
  109. ->setTableName('users')
  110. ->setIdentityColumn('username')
  111. ->setCredentialColumn('password');
  112. ]]></programlisting>
  113. <para>
  114. An diesem Punkt ist die Instanz des Authentifizierungsadapters bereit um
  115. Authentifierungsabfragen zu akzeptieren. Um eine Authentifierungsabfrage zu
  116. formulieren, werden die Eingabezeugnis Werte dem Adapter vor dem Aufruf der
  117. <code>authenticate()</code> Methode, übergeben:
  118. </para>
  119. <programlisting language="php"><![CDATA[
  120. // Die Eingabezeugnis Werte setzen (z.B. von einem Login Formular)
  121. $authAdapter
  122. ->setIdentity('my_username')
  123. ->setCredential('my_password');
  124. // Die Authentifizierungsabfrage durchführen, das Ergebnis speichern
  125. $result = $authAdapter->authenticate();
  126. ]]></programlisting>
  127. <para>
  128. Zusätzlich zum Vorhandensein der <code>getIdentity()</code> Methode über das
  129. Authentifizierungs Ergebnisobjekt, unterstützt
  130. <classname>Zend_Auth_Adapter_DbTable</classname> auch das empfangen der
  131. Tabellenzeile wenn die Authentifizierung erfolgeich war:
  132. </para>
  133. <programlisting language="php"><![CDATA[
  134. // Die Identität ausgeben
  135. echo $result->getIdentity() . "\n\n";
  136. // Die Ergebniszeile ausgeben
  137. print_r($identity);
  138. /* Ausgabe:
  139. my_username
  140. Array
  141. (
  142. [id] => 1
  143. [username] => my_username
  144. [password] => my_password
  145. [real_name] => My Real Name
  146. )
  147. */
  148. ]]></programlisting>
  149. <para>
  150. Da die Zeile der Tabelle die Zeugnis Daten enthält ist es wichtig diese Werte
  151. gegenüber unberechtigten Versuchen abzusichern.
  152. </para>
  153. </example>
  154. </sect2>
  155. <sect2 id="zend.auth.adapter.dbtable.advanced.storing_result_row">
  156. <title>Fortgeschrittene Verwendung: Ein DbTable Ergebnis Objekt dauerhaft machen</title>
  157. <para>
  158. Standardmäßig gibt <classname>Zend_Auth_Adapter_DbTable</classname> die unterstützte
  159. Identität an das Auth Objekt bei erfolgreicher Authentifizierung zurück. Ein anderes
  160. Verwendungs-Szenario, bei dem Entwickler ein Identitäts Objekt, welches andere nützliche
  161. Informationen enthält, in den dauerhaften Speichermechanismus von
  162. <classname>Zend_Auth</classname> abspeichern wollen, wird durch die Verwendung der
  163. <code>getResultRowObject()</code> Methode gelöst die ein <code>stdClass</code> Objekt
  164. zurück gibt. Der folgende Code Abschnitt zeigt diese Verwendung:
  165. </para>
  166. <programlisting language="php"><![CDATA[
  167. // Mit Zend_Auth_Adapter_DbTable authentifizieren
  168. $result = $this->_auth->authenticate($adapter);
  169. if ($result->isValid()) {
  170. // Die Identität als Objekt speichern wobei nur der Benutzername und
  171. // der echte Name zurückgegeben werden
  172. $storage = $this->_auth->getStorage();
  173. $storage->write($adapter->getResultRowObject(array(
  174. 'username',
  175. 'real_name'
  176. )));
  177. // Die Identität als Objekt speichern, wobei die
  178. // Passwort Spalte unterdrückt wird
  179. $storage->write($adapter->getResultRowObject(
  180. null,
  181. 'password'
  182. ));
  183. /* ... */
  184. } else {
  185. /* ... */
  186. }
  187. ]]></programlisting>
  188. </sect2>
  189. <sect2 id="zend.auth.adapter.dbtable.advanced.advanced_usage">
  190. <title>Forgeschrittene Verwendung durch Beispiele</title>
  191. <para>
  192. Wärend der primäre Zweck von <classname>Zend_Auth</classname> (und konsequenter Weise
  193. <classname>Zend_Auth_Adapter_DbTable</classname>) die
  194. <emphasis>Authentifizierung</emphasis> und nicht die <emphasis>Authorisierung</emphasis>
  195. ist, gibt es ein paar Instanzen und Probleme auf dem Weg welche Art besser passt.
  196. Abhängig davon wie man sich entscheidet ein Problem zu beschreiben, macht es manchmal
  197. Sinn, das was wie ein Authorisierungsproblem aussieht im Authentifizierungs-Adapter zu
  198. lösen.
  199. </para>
  200. <para>
  201. Mit dieser Definition, hat <classname>Zend_Auth_Adapter_DbTable</classname> einige
  202. eingebaute Mechanismen die für zusätzliche Checks wärend der Authentifizierungszeit
  203. angepasst werden können, um einige übliche Benutzerprobleme zu lösen.
  204. </para>
  205. <programlisting language="php"><![CDATA[
  206. // Der Feldwert des Status eines Accounts ist nicht gleich "compromised"
  207. $adapter = new Zend_Auth_Adapter_DbTable(
  208. $db,
  209. 'users',
  210. 'username',
  211. 'password',
  212. 'MD5(?) AND status != "compromised"'
  213. );
  214. // Der aktive Feldwert des Accounts ist gleich "TRUE"
  215. $adapter = new Zend_Auth_Adapter_DbTable(
  216. $db,
  217. 'users',
  218. 'username',
  219. 'password',
  220. 'MD5(?) AND active = "TRUE"'
  221. );
  222. ]]></programlisting>
  223. <para>
  224. Ein anderes Szenario kann die Implementierung eines Saltingmachanismus sein. Salting
  225. ist ein Ausdruck der auf eine Technik verweist die die Sicherheit der Anwendung sehr
  226. stark erhöht. Sie basiert auf der Idee das das Anfügen von zufälligen Strings bei jedem
  227. Passwort es unmöglich macht eine erfolgreiche Brute-Force Attacke auf die Datenbank
  228. durchzuführen bei der vorberechnete Hashwerte aus einem Verzeichnis genommen werden.
  229. </para>
  230. <para>
  231. Hierfür muß die Tabelle so modifiziert werden das Sie unseren Salt-String enthält:
  232. </para>
  233. <programlisting language="php"><![CDATA[
  234. $sqlAlter = "ALTER TABLE [users] "
  235. . "ADD COLUMN [password_salt] "
  236. . "AFTER [password]";
  237. $dbAdapter->query($sqlAlter);
  238. ]]></programlisting>
  239. <para>
  240. Hier ist ein einfacher Weg um einen Salt String für jeden Benutzer bei der Registrierung
  241. zu erstellen:
  242. </para>
  243. <programlisting language="php"><![CDATA[
  244. for ($i = 0; $i < 50; $i++) {
  245. $dynamicSalt .= chr(rand(33, 126));
  246. }
  247. ]]></programlisting>
  248. <para>
  249. Und nun erstellen wir den Adapter:
  250. </para>
  251. <programlisting language="php"><![CDATA[
  252. $adapter = new Zend_Auth_Adapter_DbTable(
  253. $db,
  254. 'users',
  255. 'username',
  256. 'password',
  257. "MD5(CONCAT('"
  258. . Zend_Registry::get('staticSalt')
  259. . "', ?, password_salt))"
  260. );
  261. ]]></programlisting>
  262. <note>
  263. <para>
  264. Die Sicherheit kann sogar noch mehr erhöht werden indem ein statischer Salt Wert
  265. hardcoded in der Anwendung verwendet wird. Im Falle das die Datenbank korrumpiert
  266. wird (z.B. durch eine SQL Injection Attacke) aber der Webserver intakt bleibt sind
  267. die Daten für den Angreifer noch immer nicht verwendbar.
  268. </para>
  269. </note>
  270. <para>
  271. Eine andere Alternative besteht darin die <code>getDbSelect()</code> Methode von
  272. Zend_Auth_Adapter_DbTable zu verwenden nachdem der Adapter erstellt wurde. Diese
  273. Methode gibt die Instanz des Zend_Db_Select Objekts zurück welches verwendet wird
  274. um die authenticate() Methode zu komplettieren. Es ist wichtig anzumerken das diese
  275. Methode immer das gleiche Objekt zurückgibt unabhängig davon ob authenticate()
  276. aufgerufen wurde oder nicht. Diese Objekt <emphasis>enthält keine</emphasis> Identity
  277. oder Anmeldeinformationen in sich da diese Werte im Select Objekt wärend des Ausführens
  278. von authenticate() platziert werden.
  279. </para>
  280. <para>
  281. Als Beispiel einer Situation könnte man die getDbSelect() Methode verwenden um
  282. den Status eines Benutzers zu prüfen, in anderen Worten sehen ob der Account des
  283. Benutzers aktiviert ist.
  284. </para>
  285. <programlisting language="php"><![CDATA[
  286. // Das Beispiel von oben weiterführen
  287. $adapter = new Zend_Auth_Adapter_DbTable(
  288. $db,
  289. 'users',
  290. 'username',
  291. 'password',
  292. 'MD5(?)'
  293. );
  294. // Das Select Objekt (durch Referenz) bekommen
  295. $select = $adapter->getDbSelect();
  296. $select->where('active = "TRUE"');
  297. // Authentifizieren, das stellt sicher das users.active = TRUE
  298. $adapter->authenticate();
  299. ]]></programlisting>
  300. </sect2>
  301. </sect1>
  302. <!--
  303. vim:se ts=4 sw=4 et:
  304. -->