Zend_Auth_Adapter_DbTable.xml 14 KB

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