Zend_Auth_Adapter_DbTable.xml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 17175 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.auth.adapter.dbtable">
  5. <title>Tabla de base de datos de autenticación</title>
  6. <sect2 id="zend.auth.adapter.dbtable.introduction">
  7. <title>Introducción</title>
  8. <para>
  9. <classname>Zend_Auth_Adapter_DbTable</classname>
  10. proporciona la
  11. capacidad de autenticar contra credenciales almacenadas en una tabla
  12. de la
  13. base de datos. Como
  14. <classname>Zend_Auth_Adapter_DbTable</classname>
  15. requiere una
  16. instancia de
  17. <classname>Zend_Db_Adapter_Abstract</classname>
  18. que
  19. será pasada a su constructor, cada instancia está vinculada a una
  20. conexión concreta de
  21. la base de datos. Se pueden establecer otras
  22. opciones de configuración a través del
  23. constructor y de métodos de
  24. instancia:
  25. </para>
  26. <para>Las opciones de configuración disponibles incluyen:
  27. </para>
  28. <itemizedlist>
  29. <listitem>
  30. <para>
  31. <emphasis>
  32. <property>tableName</property>
  33. </emphasis>
  34. : Nombre de tabla de
  35. la base de datos que contiene las credenciales de
  36. autenticación, y contra la cual se realiza la búsqueda
  37. de autenticación en la
  38. base de datos.
  39. </para>
  40. </listitem>
  41. <listitem>
  42. <para>
  43. <emphasis>
  44. <property>identityColumn</property>
  45. </emphasis>
  46. : Nombre de la
  47. columna de la tabla de la base de datos utilizada para
  48. representar
  49. la identidad. La columna identidad debe
  50. contar con valores únicos, tales como un
  51. apellido ó una
  52. dirección de e-mail.
  53. </para>
  54. </listitem>
  55. <listitem>
  56. <para>
  57. <emphasis>
  58. <property>credentialColumn</property>
  59. </emphasis>
  60. : Nombre de la
  61. columna de la tabla de la base de datos utilizada para
  62. representar
  63. la credencial. Conforme a un sistema de
  64. identidad simple y autenticación de
  65. contraseña, el valor
  66. de la credencial corresponde con la contraseña. Véase
  67. también la opción
  68. <property>credentialTreatment
  69. </property>
  70. .
  71. </para>
  72. </listitem>
  73. <listitem>
  74. <para>
  75. <emphasis>
  76. <property>credentialTreatment</property>
  77. </emphasis>
  78. : En muchos
  79. casos, contraseñas y otros datos son encriptados,
  80. mezclados, codificados, ocultados, desplazados o
  81. tratados de otra manera a través de alguna función o
  82. algoritmo. Al especificar una cadena de tratamiento
  83. parametrizada con este método, tal como
  84. <methodname>'MD5(?)'</methodname>
  85. o
  86. <methodname>'PASSWORD(?)'</methodname>
  87. , un
  88. desarrollador podría aplicar sentencias arbitrarias
  89. <acronym>SQL</acronym>
  90. sobre los datos credenciales de entrada. Ya que estas
  91. funciones son específicas de los
  92. <acronym>RDBMS</acronym>
  93. , debemos
  94. consultar el manual de la base de datos para comprobar
  95. la disponibilidad de tales funciones para su sistema de
  96. base de datos.
  97. </para>
  98. </listitem>
  99. </itemizedlist>
  100. <example id="zend.auth.adapter.dbtable.introduction.example.basic_usage">
  101. <title>Uso Básico</title>
  102. <para>
  103. Como se explicó en la introducción, el constructor
  104. <classname>Zend_Auth_Adapter_DbTable</classname>
  105. requiere
  106. una instancia de
  107. <classname>Zend_Db_Adapter_Abstract</classname>
  108. que sirve como conexión a la base de datos a la cual la
  109. instancia de autenticación
  110. está obligada a adaptarse. En primer
  111. lugar, la conexión de la base de datos debe ser
  112. creada.
  113. </para>
  114. <para>
  115. El siguiente código crea un adaptador para una base de datos
  116. en memoria , un esquema
  117. simple de la tabla, e inserta una fila
  118. contra la que se pueda realizar una consulta
  119. de autenticación
  120. posterior. Este ejemplo requiere que la extensión
  121. <acronym>PDO</acronym>
  122. SQLite
  123. esté disponible.
  124. </para>
  125. <programlisting language="php"><![CDATA[
  126. // Crear una conexión en memoria de la bade de datos SQLite
  127. $dbAdapter = new Zend_Db_Adapter_Pdo_Sqlite(array('dbname' =>
  128. ':memory:'));
  129. // Construir mediante una consulta una simple tabla
  130. $sqlCreate = 'CREATE TABLE [users] ('
  131. . '[id] INTEGER NOT NULL PRIMARY KEY, '
  132. . '[username] VARCHAR(50) UNIQUE NOT NULL, '
  133. . '[password] VARCHAR(32) NULL, '
  134. . '[real_name] VARCHAR(150) NULL)';
  135. // Crear las credenciales de autenticación de la tabla
  136. $dbAdapter->query($sqlCreate);
  137. // Construir una consulta para insertar una fila para que se pueda realizar la autenticación
  138. $sqlInsert = "INSERT INTO users (username, password, real_name) "
  139. . "VALUES ('my_username', 'my_password', 'My Real Name')";
  140. // Insertar los datos
  141. $dbAdapter->query($sqlInsert);
  142. ]]></programlisting>
  143. <para>
  144. Con la conexión de la base de datos y los datos de la tabla
  145. disponibles, podemos
  146. crear un instancia de
  147. <classname>Zend_Auth_Adapter_DbTable</classname>
  148. . Los
  149. valores de las opciones de configuración pueden ser pasados al
  150. constructor o
  151. pasados como parámetros a los métodos setter
  152. después de ser instanciados.
  153. </para>
  154. <programlisting language="php"><![CDATA[
  155. // Configurar la instancia con los parámetros del constructor...
  156. $authAdapter = new Zend_Auth_Adapter_DbTable(
  157. $dbAdapter,
  158. 'users',
  159. 'username',
  160. 'password'
  161. );
  162. // ...o configurar la instancia con los métodos setter.
  163. $authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
  164. $authAdapter
  165. ->setTableName('users')
  166. ->setIdentityColumn('username')
  167. ->setCredentialColumn('password')
  168. ;
  169. ]]></programlisting>
  170. <para>
  171. En este punto, el adaptador de la instancia de autenticación
  172. está listo para aceptar
  173. consultas de autenticación. Con el fin
  174. de elaborar una consulta de autenticación, los
  175. valores de
  176. entrada de la credencial son pasados por el adaptador ates de
  177. llamar al
  178. método
  179. <methodname>authenticate()</methodname>
  180. :
  181. </para>
  182. <programlisting language="php"><![CDATA[
  183. // Seleccionamos los valores de entrada de la credencial (e.g., de un formulario de acceso)
  184. $authAdapter
  185. ->setIdentity('my_username')
  186. ->setCredential('my_password')
  187. ;
  188. // Ejecutamos la consulta de autenticación, salvando los resultados
  189. ]]></programlisting>
  190. <para>
  191. Además de la disponibilidad del método
  192. <methodname>getIdentity()</methodname>
  193. sobre el objeto
  194. resultante de la autenticación,
  195. <classname>Zend_Auth_Adapter_DbTable</classname>
  196. también
  197. ayuda a recuperar la fila de al tabla sobre la autenticación
  198. realizada.
  199. </para>
  200. <programlisting language="php"><![CDATA[
  201. // Imprimir la identidad
  202. echo $result->getIdentity() . "\n\n";
  203. // Imprimir la fila resultado
  204. print_r($authAdapter->getResultRowObject());
  205. /* Salida:
  206. my_username
  207. Array
  208. (
  209. [id] => 1
  210. [username] => my_username
  211. [password] => my_password
  212. [real_name] => My Real Name
  213. )
  214. ]]></programlisting>
  215. <para>Ya que la fila de la tabla contiene el valor de la
  216. credencial, es importante
  217. proteger los valores contra accesos no
  218. deseados.</para>
  219. </example>
  220. </sect2>
  221. <sect2 id="zend.auth.adapter.dbtable.advanced.storing_result_row">
  222. <title>Advanced Usage: Manteniendo el resultado del Objeto
  223. DbTable</title>
  224. <para>
  225. Por defecto,
  226. <classname>Zend_Auth_Adapter_DbTable</classname>
  227. devuelve la identidad proporcionada al objeto Auth en la
  228. autenticación realizada. Otro de
  229. los casos de uso, donde los
  230. desarrolladores desean guardar para mantener el mecanismo de
  231. almacenamiento de un objeto identidad
  232. <classname>Zend_Auth</classname>
  233. que contiene información útil,
  234. se resuelve usando el método
  235. <methodname>getResultRowObject()</methodname>
  236. para devolver un
  237. objeto
  238. <emphasis>stdClass</emphasis>
  239. . El siguiente fragmento de
  240. código muestra su uso:
  241. </para>
  242. <programlisting language="php"><![CDATA[
  243. // Autenticar con Zend_Auth_Adapter_DbTable
  244. $result = $this->_auth->authenticate($adapter);
  245. if ($result->isValid()) {
  246. // Almacena la identidad como un objedo dónde solo username y
  247. // real_name han sido devueltos
  248. $storage = $this->_auth->getStorage();
  249. $storage->write($adapter->getResultRowObject(array(
  250. 'username',
  251. 'real_name',
  252. )));
  253. // Almacena la identidad como un objeto dónde la columna contraseña ha
  254. // sido omitida
  255. $storage->write($adapter->getResultRowObject(
  256. null,
  257. 'password'
  258. ));
  259. /* ... */
  260. } else {
  261. /* ... */
  262. }
  263. ]]></programlisting>
  264. </sect2>
  265. <sect2 id="zend.auth.adapter.dbtable.advanced.advanced_usage">
  266. <title>Ejemplo de Uso Avanzado</title>
  267. <para>
  268. Si bien el objetivo primordial de
  269. <classname>Zend_Auth</classname>
  270. (y, por consiguiente,
  271. <classname>Zend_Auth_Adapter_DbTable</classname>
  272. ) es
  273. principalmente la
  274. <emphasis>autenticación</emphasis>
  275. y no la
  276. <emphasis>autorización</emphasis>
  277. , hay unos pocos casos y
  278. problemas que se encuentran al límite entre cuales encajan
  279. dentro
  280. del dominio. Dependiendo de cómo haya decidido explicar su problema,
  281. a veces tiene
  282. sentido resolver lo que podría parecer un problema de
  283. autorización dentro de un adaptador
  284. de autenticación.
  285. </para>
  286. <para>
  287. Con esa excepción fuera de lo común,
  288. <classname>Zend_Auth_Adapter_DbTable</classname>
  289. ha construido
  290. mecanismos que pueden ser aprovechados para realizar controles
  291. adicionales
  292. en la autenticación a la vez que se resuelven algunos
  293. problemas comunes de los usuarios.
  294. </para>
  295. <programlisting language="php"><![CDATA[
  296. // El valor del campo status de una cuenta no es igual a "compromised"
  297. $adapter = new Zend_Auth_Adapter_DbTable(
  298. $db,
  299. 'users',
  300. 'username',
  301. 'password',
  302. 'MD5(?) AND status != "compromised"'
  303. );
  304. // El valor del campo active de una cuenta es igual a "TRUE"
  305. $adapter = new Zend_Auth_Adapter_DbTable(
  306. $db,
  307. 'users',
  308. 'username',
  309. 'password',
  310. 'MD5(?) AND active = "TRUE"'
  311. ]]></programlisting>
  312. <para>Otra idea puede ser la aplicación de un mecanismo de "salting".
  313. "Salting" es un término
  314. que se refiere a una técnica que puede
  315. mejorar altamente la seguridad de su aplicación.
  316. Se basa en la idea
  317. de concatenar una cadena aleatoria a cada contraseña para evitar un
  318. ataque de fuerza bruta sobre la base de datos usando los valores
  319. hash de un diccionario
  320. pre-calculado.</para>
  321. <para>Por lo tanto, tenemos que modificar nuestra tabla para almacenar
  322. nuestra cadena
  323. mezclada:</para>
  324. <programlisting language="php"><![CDATA[
  325. $sqlAlter = "ALTER TABLE [users] "
  326. . "ADD COLUMN [password_salt] "
  327. . "AFTER [password]";
  328. ]]></programlisting>
  329. <para>Aquí hay una forma sencilla de generar una cadena mezclada por
  330. cada usuario en el
  331. momento del registro:</para>
  332. <programlisting language="php"><![CDATA[
  333. for ($i = 0; $i < 50; $i++) {
  334. $dynamicSalt .= chr(rand(33, 126));
  335. ]]></programlisting>
  336. <para>Y ahora vamos a construir el adaptador:</para>
  337. <programlisting language="php"><![CDATA[
  338. $adapter = new Zend_Auth_Adapter_DbTable(
  339. $db,
  340. 'users',
  341. 'username',
  342. 'password',
  343. "MD5(CONCAT('"
  344. . Zend_Registry::get('staticSalt')
  345. . "', ?, password_salt))"
  346. );
  347. ]]></programlisting>
  348. <note>
  349. <para>
  350. Puede mejorar aún más la seguridad mediante el uso de un
  351. valor 'salt' estático
  352. fuertemente codificado en su aplicación.
  353. En el caso de que su base de datos se vea
  354. comprometida (por
  355. ejemplo, por un ataque de inyección
  356. <acronym>SQL</acronym>
  357. ), su servidor web está
  358. intacto y sus datos son inutilizable para el atacante.
  359. </para>
  360. </note>
  361. <para>
  362. Otra alternativa es utilizar el método
  363. <methodname>getDbSelect()</methodname>
  364. de
  365. <classname>Zend_Auth_Adapter_DbTable</classname>
  366. después de que el adaptador se ha
  367. construido. Este método devolverá la instancia del
  368. objeto
  369. <classname>Zend_Db_Select</classname>
  370. que se va a utilizar para completar la rutina de
  371. authenticate(). Es importante señalar
  372. que este método siempre
  373. devuelve el mismo objeto, independientemente de si
  374. <methodname>authenticate()</methodname>
  375. ha
  376. sido llamado o no. Este objeto
  377. <emphasis>no tendrá</emphasis>
  378. ninguna de las credenciales de identidad o información de como estos
  379. valores son
  380. colocados dentro del objeto seleccionado en
  381. <methodname>authenticate()</methodname>
  382. .
  383. </para>
  384. <para>
  385. Un ejemplo de una situación en la que uno podría querer utilizar
  386. el método
  387. <methodname>getDbSelect()</methodname>
  388. sería comprobar el estado de un usuario, en
  389. otras palabras, ver si la cuenta del usuario
  390. está habilitada.
  391. </para>
  392. <programlisting language="php"><![CDATA[
  393. // Continuando con el ejemplo de arriba
  394. $adapter = new Zend_Auth_Adapter_DbTable(
  395. $db,
  396. 'users',
  397. 'username',
  398. 'password',
  399. 'MD5(?)'
  400. );
  401. // obtener el objeto select (por referencia)
  402. $select = $adapter->getDbSelect();
  403. $select->where('active = "TRUE"');
  404. // authenticate, esto asegura que users.active = TRUE
  405. $adapter->authenticate();
  406. ]]></programlisting>
  407. </sect2>
  408. </sect1>