Zend_Auth_Adapter_DbTable.xml 13 KB

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