Zend_Auth_Adapter_DbTable.xml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect1 id="zend.auth.adapter.dbtable">
  4. <title>Database Table Authentication</title>
  5. <sect2 id="zend.auth.adapter.dbtable.introduction">
  6. <title>Introduzione</title>
  7. <para>
  8. <classname>Zend_Auth_Adapter_DbTable</classname> fornisce la possibilità di
  9. autenticare un utente secondo le credenziali memorizzate in una tabella di un database. Dato che
  10. <classname>Zend_Auth_Adapter_DbTable</classname> necessita che un'istanza della classe
  11. <classname>Zend_Db_Adapter_Abstract</classname> sia passata al suo
  12. costruttore, ogni istanza è legata ad una particolare connessione al
  13. database. Altre opzioni di configurazione possono essere impostate tramite il
  14. costruttore e tramite i metodi dell'instanza, una per ogni opzione.
  15. </para>
  16. <para>
  17. Le opzioni di configurazione disponibili includono:
  18. </para>
  19. <itemizedlist>
  20. <listitem>
  21. <para>
  22. <emphasis><property>tableName</property></emphasis>: Indica il nome della tabella del database che contiene le credenziali di autenticazione, e in quale database la query di autenticazione viene effettuata.
  23. </para>
  24. </listitem>
  25. <listitem>
  26. <para>
  27. <emphasis><property>identityColumn</property></emphasis>: Indica il nome della colonna della tabella usata per rappresentare l'identità. La colonna dell'identità deve contenere valori univoci, come ad esempio il nome utente o l'indirizzo email.
  28. </para>
  29. </listitem>
  30. <listitem>
  31. <para>
  32. <emphasis><property>credentialColumn</property></emphasis>: Indica il nome della colonna della tabella usata per rappresentare le credenziali. Sotto un semplice schema di identità e password, il valore della credenziale corrisponde alla password. Vedere anche l'opzione <property>credentialTreatment</property>
  33. </para>
  34. </listitem>
  35. <listitem>
  36. <para>
  37. <emphasis><property>credentialTreatment</property></emphasis>: In molti casi, le password e altre informazioni sensibili sono criptate, memorizzate attraverso algoritmi di hash, codificate, oscurate o trattate con funzioni o algoritmi. Specificando una stringa con questo metodo, come ad esempio '<methodname>MD5(?)</methodname>' oppure
  38. '<methodname>PASSWORD(?)</methodname>', uno sviluppatore può applicare credenziali in <acronym>SQL</acronym>.
  39. Dato che queste funzioni sono specifiche all'<acronym>RDBMS</acronym> utilizzato, vedere il manuale per verificare la compatibilità di queste funzioni con il vostro database.
  40. </para>
  41. </listitem>
  42. </itemizedlist>
  43. <example id="zend.auth.adapter.dbtable.introduction.example.basic_usage">
  44. <title>Utilizzo base</title>
  45. <para>
  46. Come illustrato nell'introduzione, il costruttore della <classname>Zend_Auth_Adapter_DbTable</classname> ha bisogno di un'istanza di <classname>Zend_Db_Adapter_Abstract</classname> che viene utilizzata come connessione al database per l'autenticazione. Prima di tutto, la connessione al database dovrebbe essere creata.
  47. </para>
  48. <para>
  49. Il codice seguente crea un adapter per un database in-memory, crea un semplice schema di una tabella, e inserisce una riga su cui più tardi sarà possibile effettuare la query di autenticazione. Questo esempio ha bisogno che l'estensione <acronym>PDO</acronym> SQLite sia disponibile:
  50. </para>
  51. <programlisting language="php"><![CDATA[
  52. // Crea una connessione al database SQLite "in-memory"
  53. $dbAdapter = new Zend_Db_Adapter_Pdo_Sqlite(array('dbname' =>
  54. ':memory:'));
  55. // Costruisce una semplice tabella
  56. $sqlCreate = 'CREATE TABLE [users] ('
  57. . '[id] INTEGER NOT NULL PRIMARY KEY, '
  58. . '[username] VARCHAR(50) UNIQUE NOT NULL, '
  59. . '[password] VARCHAR(32) NULL, '
  60. . '[real_name] VARCHAR(150) NULL)';
  61. // Crea la tabella che contiene le credenziali di autenticazione
  62. $dbAdapter->query($sqlCreate);
  63. // Costruisce una query per inserire una riga per cui l'autenticazione possa andare a buon fine
  64. $sqlInsert = "INSERT INTO users (username, password, real_name) "
  65. . "VALUES ('my_username', 'my_password', 'My Real Name')";
  66. // Inserisce le informazioni
  67. $dbAdapter->query($sqlInsert);
  68. ]]></programlisting>
  69. <para>
  70. Con la connessione al database e i dati della tabella disponibili, un'instanza di <classname>Zend_Auth_Adapter_DbTable</classname> può essere creata. I valori delle opzioni di configurazione possono essere passati al costruttore o passati come parametri ai metodi di configurazione dopo l'istanziazione:
  71. </para>
  72. <programlisting language="php"><![CDATA[
  73. // Configurare l'istanza con i parametri del costruttore
  74. $authAdapter = new Zend_Auth_Adapter_DbTable(
  75. $dbAdapter,
  76. 'users',
  77. 'username',
  78. 'password'
  79. );
  80. // ...oppure configurare l'istanza con i metodi di configurazione
  81. $authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
  82. $authAdapter
  83. ->setTableName('users')
  84. ->setIdentityColumn('username')
  85. ->setCredentialColumn('password')
  86. ;
  87. ]]></programlisting>
  88. <para>
  89. A questo punto, l'istanza dell'adapter di autenticazione è pronta ad accettare le query di autenticazione. Al fine di formulare una query di autenticazione, i valori di input sono passati all'adapter prima di chiamare il metodo <methodname>authenticate()</methodname>:
  90. </para>
  91. <programlisting language="php"><![CDATA[
  92. // Impostare i valori delle credenziali (e.g., da un form di login)
  93. $authAdapter
  94. ->setIdentity('my_username')
  95. ->setCredential('my_password')
  96. ;
  97. // Effettua la query di autenticazione, salvando il risultato
  98. ]]></programlisting>
  99. <para>
  100. Oltre alla disponibilità del metodo <methodname>getIdentity()</methodname> sull'oggetto che contiene il risultato dell'autenticazione, <classname>Zend_Auth_Adapter_DbTable</classname> supporta anche il recupero della riga della tabella su cui l'autenticazione è avvenuta con successo:
  101. </para>
  102. <programlisting language="php"><![CDATA[
  103. // Stampa l'identità
  104. echo $result->getIdentity() . "\n\n";
  105. // Stampa la riga di risultato
  106. print_r($authAdapter->getResultRowObject());
  107. /* Output:
  108. my_username
  109. Array
  110. (
  111. [id] => 1
  112. [username] => my_username
  113. [password] => my_password
  114. [real_name] => My Real Name
  115. )
  116. ]]></programlisting>
  117. <para>
  118. Dato che la riga della tabella contiene le credenziali, è importante mettere in sicurezza questi dati da accessi indesiderati.
  119. </para>
  120. </example>
  121. </sect2>
  122. <sect2 id="zend.auth.adapter.dbtable.advanced.storing_result_row">
  123. <title>Utilizzo avanzato: Rendere persistente un oggetto di risultato di tipo DbTable</title>
  124. <para>
  125. Di default, la classe <classname>Zend_Auth_Adapter_DbTable</classname> restituisce l'identità fornita all'oggetto di autenticazione dopo che l'autenticazione ha avuto successo. Un altro scenario, in cui gli sviluppatori vogliono memorizzare nel meccanismo di memorizzazione persistente della classe <classname>Zend_Auth</classname> un oggetto di identità contenente altre utili informazioni, è gestito usando il metodo <methodname>getResultRowObject()</methodname> per restituire un oggetto <emphasis>stdClass</emphasis>. Il seguente codice illustra il suo uso:
  126. </para>
  127. <programlisting language="php"><![CDATA[
  128. // autenticazione con Zend_Auth_Adapter_DbTable
  129. $result = $this->_auth->authenticate($adapter);
  130. if ($result->isValid()) {
  131. // memorizzazione dell'identità come un oggetto in cui solo lo username e
  132. // il real_name vengono restituiti
  133. $storage = $this->_auth->getStorage();
  134. $storage->write($adapter->getResultRowObject(array(
  135. 'username',
  136. 'real_name',
  137. )));
  138. // memorizza l'identità come un oggetto in cui la colonna password
  139. // viene omessa
  140. $storage->write($adapter->getResultRowObject(
  141. null,
  142. 'password'
  143. ));
  144. /* ... */
  145. } else {
  146. /* ... */
  147. }
  148. ]]></programlisting>
  149. </sect2>
  150. <sect2 id="zend.auth.adapter.dbtable.advanced.advanced_usage">
  151. <title>Esempio di un utilizzo avanzato</title>
  152. <para>
  153. Mentre il proposito principale della <classname>Zend_Auth</classname> (e conseguentemente <classname>Zend_Auth_Adapter_DbTable</classname>) è principalmente l'<emphasis>autenticazione</emphasis> e non l'<emphasis>autorizzazione</emphasis>, ci sono un pò di istanze e problemi che segnano la linea in quale dominio loro dovrebbero essere utilizzati. A seconda di come si è deciso di spiegare il problema, a volte ha senso risolvere quello che potrebbe sembrare un problema di autenticazione con l'adapter autentication.
  154. </para>
  155. <para>
  156. Senza l'ostacolo del disclaimer, la classe <classname>Zend_Auth_Adapter_DbTable</classname> ha alcuni meccanismi interni che possono essere influenzati da ulteriori controlli nel momento dell'autenticazione per risolvere alcuni comuni problemi dell'utente.
  157. </para>
  158. <programlisting language="php"><![CDATA[
  159. // Il valore del campo di stato di un account non è uguale a "compromised"
  160. $adapter = new Zend_Auth_Adapter_DbTable(
  161. $db,
  162. 'users',
  163. 'username',
  164. 'password',
  165. 'MD5(?) AND status != "compromised"'
  166. );
  167. // Il valore del campo attivo di un account è uguale a TRUE
  168. $adapter = new Zend_Auth_Adapter_DbTable(
  169. $db,
  170. 'users',
  171. 'username',
  172. 'password',
  173. 'MD5(?) AND active = "TRUE"'
  174. ]]></programlisting>
  175. <para>
  176. Un altro scenario può essere l'implementazione di un meccanismo di "salting". Il salting è un termine che si riferisce alla tecnica con la quale si può migliorare di molto la sicurezza dell'applicazione. E' basata sull'idea che concatenando una stringa casuale ad ogni password rende impossibile un attacco di tipo "brute force" sul database usando un dizionario di parole pre-confezionate.
  177. </para>
  178. <para>
  179. Quindi, è necessario modificare la tabella per memorizzare la stringa "salt".
  180. </para>
  181. <programlisting language="php"><![CDATA[
  182. $sqlAlter = "ALTER TABLE [users] "
  183. . "ADD COLUMN [password_salt] "
  184. . "AFTER [password]";
  185. ]]></programlisting>
  186. <para>
  187. Di seguito un semplice modo per generare la stringa "salt" per ogni utente alla registrazione:
  188. </para>
  189. <programlisting language="php"><![CDATA[
  190. for ($i = 0; $i < 50; $i++) {
  191. $dynamicSalt .= chr(rand(33, 126));
  192. ]]></programlisting>
  193. <para>
  194. E ora compilare l'adapter:
  195. And now let's build the adapter:
  196. </para>
  197. <programlisting language="php"><![CDATA[
  198. $adapter = new Zend_Auth_Adapter_DbTable(
  199. $db,
  200. 'users',
  201. 'username',
  202. 'password',
  203. "MD5(CONCAT('"
  204. . Zend_Registry::get('staticSalt')
  205. . "', ?, password_salt))"
  206. );
  207. ]]></programlisting>
  208. <note>
  209. <para>
  210. E' possibile migliorare la sicurezza ancora di più usando un valore statico di "salt" inserito manualmente nel nell'applicazione. Nel caso in cui il database sia compromesso (per esempio da un attacco <acronym>SQL</acronym> injection) ma il web server sia intego e le informazioni ancora inutilizzabili da chi ha effettuato l'attacco.
  211. </para>
  212. </note>
  213. <para>
  214. Un'alternativa è usare il metodo <methodname>getDbSelect()</methodname> della classe <classname>Zend_Auth_Adapter_DbTable</classname> dopo che l'adapter è stato costruito. Questo metodo restituisce l'istanza dell'oggetto <classname>Zend_Db_Select</classname> e la userà per completare il metodo <methodname>authenticate()</methodname>.
  215. E' importante notare che questo metodo restituisce sempre lo stesso oggetto indipendentemente dal fatto che il metodo <methodname>authenticate()</methodname> è stato chiamato o meno. Questo oggetto <emphasis>non avrà</emphasis> nessuna delle informazioni relative all'identità o alle credenziali poichè quei valori sono stati inseriti nell'oggetto select nel momento in cui il metodo <methodname>authenticate()</methodname> viene eseguito.
  216. </para>
  217. <para>
  218. Un esempio della situazione in cui si voglia usare il metodo <methodname>getDbSelect()</methodname> per controllare lo stato di un utente, in altre parole per vedere se quell'account utente è abilitato.
  219. </para>
  220. <programlisting language="php"><![CDATA[
  221. // Continua con l'esempio di sopra
  222. $adapter = new Zend_Auth_Adapter_DbTable(
  223. $db,
  224. 'users',
  225. 'username',
  226. 'password',
  227. 'MD5(?)'
  228. );
  229. // prende l'oggette "select"
  230. $select = $adapter->getDbSelect();
  231. $select->where('active = "TRUE"');
  232. // metodo authenticate, questo assicura che users.active = TRUE
  233. $adapter->authenticate();
  234. ]]></programlisting>
  235. </sect2>
  236. </sect1>