Aunque parece sencillo hacer que tus pestañas de Bootstrap sean responsive, a veces la documentación no lo deja suficientemente claro. En este vídeo analizamos la problemática y después de valorar algunas soluciones propongo la que considero la más apropiada.
Simulando un archivador con HTML y CSS
Explicación para no programadores de JWT (Json Web Token)
Me estreno como podcaster – Devirtualize: un podcast sobre tecnología y programación
Llevaba bastante tiempo hablando con mi amigo Pablo Baenas Castelló de a ver si hacíamos un podcast y finalmente hemos creado Devirtualize: un podcast sobre tecnología y programación. Como no sabíamos por donde empezar al final hemos pensado en comenzar por algo que domináramos, así que el primer episodio va sobre Openbravo. Probablemente el segundo lo haremos sobre nuestra experiencia montando y trabajando en E-Commerce (en este momento estamos preparando el guion). Os dejo los enlaces para poder escucharlo:
Cómo migrar el sistema de cifrado de contraseñas a uno más robusto
En un apunte anterior de la bitácora explicaba como gestionar contraseñas seguras en PHP. Pero, qué sucede si por inexperiencia empezamos a guardar las contraseñas en plano y queremos migrar a un sistema seguro? O aún más complicado, y si empezamos a usar un sistema tipo hash que pensábamos que era seguro como sha1 pero que se ha demostrado que no lo es? Veamos los dos casos por separado.
Pasar de contraseñas en plano a cifradas
Este es el caso más fácil de solventar ya que simplemente tendremos que generar el hash con salt de todas las contraseñas y empezar a utilizarlo. Ahora bien, como no queremos que nuestro sistema en producción se detenga podemos hacerlo de la siguiente manera.
- Añadimos una nueva columna a nuestra tabla en base de datos en caso de utilizar un sistema de gestión de base de datos relacional o un dato nuevo dependiendo del sistema que utilicemos.
- Generaremos la nueva contraseña cifrada para cada usuario y la almacenaremos en la nueva columna.
- Cambiaremos nuestro código para que cuando se cree un nuevo usuario la contraseña se genere y guarde cifrada, lo mismo en el caso de que se permita el cambio de contraseña. También que cuando se autentique un usuario se compruebe con el nuevo sistema. Esto lo podremos hacer porque tendremos la columna con la contraseña nueva cifrada y segura.
- Una vez testeado que todo funciona subiremos este nuevo código a producción.
- Ahora ya podemos hacer un update en la base de datos de forma que machaquemos las contraseñas en plano por las cifradas, sería algo así:
update usuario set passwd = new_passwd;
En este punto ya no tendremos contraseñas en plano sino que todo estará cifrado. Ya nos podemos olvidar de problemas de seguridad derivados de las contraseñas en plano. - Cambiaremos de nuevo el código para que utilice la columna original y deje de hacerlo en la nueva. Después de testarlo se subirá a producción.
- Y por último ya podremos borrar la columna de la contraseña nueva porque ya no será necesaria.
El punto 2 en el que generamos las nuevas contraseñas cifradas es un proceso largo dependiendo de cuantos usuarios tengamos en la base de datos y de lo rápida que sea nuestra máquina en hacer este cambio ya que generalmente tendrá que leer la contraseña en plano almacenada en la base de datos, cifrarla y luego asignar el resultado a la nueva columna para la nueva contraseña, y así uno por uno por cada usuario que tengamos. Esto puede dar pie a que cuando se termine el proceso ya hayan cambiado algunas de las contraseñas originales, cuidado con esto.
En cuanto al punto 5 y 6 debe estar optimizado para que no haya retrasos y se produzcan efectos como que se haya generado una contraseña en la columna nueva (un nuevo usuario por ejemplo) después de haber hecho el update y por tanto nunca aparezca en la columna original. Para esto se puede utilizar trucos como meter los dos pasos en una única transacción o cambiar el código momentáneamente para que cree las contraseñas sobre las dos columnas, etc. Todo va a depender del tráfico que tengáis, los servidores que utilicéis (un mysql con master slave también puede ayudar por ejemplo) para que esto realmente sea un problema. De todas formas lo suyo es luego hacer tracing de la base de datos para ver que todo se ha quedado bien.
Pasar de contraseñas en Hash inseguras a cifradas en un sistema más seguro
Hacer está migración es bastante más complicada que la anterior ya que al no tener las contraseñas originales en plano es imposible generar el nuevo Hash con Salt. Pero no está todo perdido, si lo piensas si que hay un punto en el que podemos obtener la contraseña en plano original y es en el momento de la autenticación ya que el usuario introducirá su contraseña, luego con un hash tipo sha1 lo que se haría es generar el sha1 y comparar, si da ok es que lo que nos pasaron era la contraseña en plano original.
Aprovechando esto lo que suelo hacer yo es utilizar una técnica que se suele conocer como hacer un cambio o actualización «lazy» o dicho en español «perezosa». En qué consiste? básicamente en que cada vez que un usuario se autentica comprobamos su contraseña con el sistema antiguo, si este da ok entonces utilizamos la contraseña en plano obtenida para generar la contraseña cifrada nueva y guardarla. Si todo va bien poco a poco los usuarios irán migrando de un sistema a otro de forma transparente para ellos. Sin darse cuenta terminan con una contraseña almacenada de forma mucho más segura. Veamos como lo haríamos.
- Igual que en caso anterior añadimos una nueva columna a nuestra tabla en base de datos que será donde se almacena la nueva contraseña cifrada.
- Cambiamos nuestro código de forma que intente autenticar con el sistema nuevo, si da error lo que hacemos es intentarlo con el antiguo y en caso de que de ok con el segundo entonces generamos la nueva contraseña y la guardamos, al mismo tiempo ponemos a null la vieja.
- Después de testear el nuevo código lo subimos a producción.
- Haremos tracing de la base de datos para ver que efectivamente las contraseñas se están migrando correctamente a medida que los usuarios van entrando.
Esta técnica es una buena opción porque nos evita forzar a todos los usuarios a cambiar la contraseña, pero tiene una pega, no nos asegura que todos los usuarios terminen migrando la contraseña ya que siempre tendremos usuarios residuales que nunca volverán a autenticarse. Lo que se puede hacer es que después de que pase un tiempo que dependerá de los usuarios que tengáis, realizar una limpieza final de la base de datos dejando sin contraseña a los usuarios residuales y de este modo forzándoles a generar una nueva en caso de que vuelvan a entrar.
Si tenéis alguna duda sobre estos procesos la podéis dejar en los comentarios. Chauuuu.
Explicación del Patrón de Diseño Software «Inyección de Dependencias»
Contraseñas seguras en PHP
Guardar las contraseñas de forma segura en base de datos es uno de los procesos más habituales y más importante de cualquier aplicación con usuarios. En PHP es muy sencillo hacerlo, pero antes vamos a explicar cuales son los problemas y las soluciones para generar y guardar contraseñas seguras.
Lo primero y más importante es que nunca debemos guardar en plano las contraseñas en la base de datos. El motivo es que si nuestra base de datos se ve comprometida el nombre de usuario y la contraseña puede ser usado en otras webs ya que la mayoría de la gente los reutiliza. Que levante la mano quien no tenga la misma contraseña en decenas de webs.
Entonces, ¿cómo las guardamos?. Podríamos hacerlo utilizando alguno de los algoritmos de hash más comunes como son md5 o sha1 pero por una parte estos algoritmos llevan rotos desde hace años y por otra se podrían utilizan tablas arcoíris (rainbow tables) que no son ni más ni menos que tablas de contraseñas con el hash ya generado de forma que es mucho más sencillo realizar un ataque de fuerza bruta.
Para evitar este tipo de ataques utilizaremos Salt. Pero ¿qué es Salt? Esta técnica consiste en añadir una cadena aleatoria a la contraseña antes de que se utilice para generar el hash. Pongamos un ejemplo sencillo para que se entienda, digamos que la contraseña es la palabra «hola», lo que vamos a hacer es generar una cadena aleatoria que deberemos guardar en base de datos para poder regenerar el hash de nuevo. Ahora lo que hacemos es por ejemplo concatenar la contraseña con la cadena aleatoria y sobre el resultado de la concatenación generamos el hash. Vendría a ser algo así:
hash(«hola» . «A%$bcJeL»)
La función hash podría ser cualquier función hash segura, el resultado de la cual es lo que guardaremos en base de datos como contraseña y como ya habíamos mencionado también guardaremos el Salt «A%$bcJeL» en el ejemplo para en algún momento poder regenerar el hash y así poder comprobar la contraseña. Para comprobarla lo que haríamos es recuperar el hash y el Salt de base de datos, regenerar el hash con la contraseña que introduzca el usuario en el formulario correspondiente y comparar. Sería algo así:
hash($campoFormulario . $saltDeBaseDeDatos) == $contrasenyaDeBaseDeDatos
Ahora la tabla arcoíris ya no sirve porque los hashes resultantes al tener Salt serán completamente diferentes.
Una vez hemos entendido todo esto ¿cual es la forma correcta de hacerlo en PHP? Pues usar las funciones password_hash y password_verify. La primera genera un hash con Salt de forma automática, nosotros lo único que tenemos que darle es la contraseña en plano y el algoritmo seguro a utilizar para generar el hash. Actualmente se recomienda el algoritmo CRYPT_BLOWFISH pero si le indicamos PASSWORD_DEFAULT como algoritmo entonces la función utilizará el aceptado como más seguro en ese momento de forma que si sale uno mejor será ese el que se empiece a utilizar.
password_hash ( string $password
, integer $algo
[, array $options
] ) : string
En el ejemplo sería:
password_hash(«hola», PASSWORD_BCRYPT)
Esto nos generar un hash con este formato:
Como veis tenemos todo lo necesario en un único hash. El tipo de algoritmo que en nuestro caso es CRYPT_BLOWFISH, las opciones del algoritmo si las hubiera, el Salt y el hash de la contraseña. Ahora tan solo necesitamos guardar este hash completo en la base de datos en lugar del hash y el Salt por separado.
Si queremos comprobar la contraseña usaremos la función password_verify a la que tan solo tendríamos que pasarle por un lado la contraseña y por otro el hash completo ya que ahí tiene todos los datos necesarios para la comprobación.
password_verify ( string $password
, string $hash
) : bool
Esta función internamente hace algo parecido a lo que hacíamos nosotros en el ejemplo de comprobación con Salt devolviéndonos al final verdadero o falso dependiendo de si la contraseña coincide o no.
Con todo esto ya sabéis como generar un hash seguro y como comprobar la validez de vuestras contraseñas a partir del hash. Pero si tienes cualquier duda déjamela en un comentario.
Nos vemos.
Emular terminal desde PHP en Servidores Virtuales Gestionados (caso de Comvive)
Desde que trabajo en Pórtico Legal quería empezar a usar el sistema de control de versiones (yo siempre lo uso y aquí no tenían nada, una locura) y poder usarlo para los despliegues en preproducción y producción como solución intermedia hasta que tengamos algo más avanzado. Hasta la fecha se estaban haciendo mediante ftp con todos los problemas que eso supone, entre ellos los siguientes y sus posibles soluciones:
- Mientras se ha subido un archivo y se está subiendo otro que depende de este la web se puede romper, lo más probable es que ocurra. Esto no se solventa completamente usando git sobre un único servidor pero se minimiza muchísimo.
- Nunca se sabe que versión está en producción. En algunos momento se habían subido archivos por diferentes personas y una no sabía lo que había subido la otra.
- Si se toca algo en el servidor un simple «git status» te lo va a chivar, y un simple «git checkout …» te va a solucionar la papeleta.
- Se va a poder desplegar nuevas versiones simplemente etiquetando y haciendo un «git checkout tag«
Aquí el problema venía por parte del hosting de comvive que al ser un VPS gestionado no te dan cuenta de shell. Para solucionarlo al final utilicé un pequeño script php que ejecutaba la orden que le pasas como parámetro:
<?php
$command = $_GET[«command»];
$res = execute($command, __DIR__ . ‘/..’);
echo «<pre>»;
echo «\nCódigo de salida: » . $res[‘code’];
echo «\n» . $res[‘out’];
echo «\nSalida de error:\n» . $res[‘err’];
echo «</pre>»;
function execute($cmd, $workdir = null) {
if (is_null($workdir)) {
$workdir = __DIR__;
}
$descriptorspec = array(
0 => array(«pipe», «r»), // stdin
1 => array(«pipe», «w»), // stdout
2 => array(«pipe», «w»), // stderr
);
$process = proc_open($cmd, $descriptorspec, $pipes, $workdir, null);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
return [
‘code’ => proc_close($process),
‘out’ => trim($stdout),
‘err’ => trim($stderr),
];
}
La etiqueta pre la utilizo para que la salida se vea bien si la llamamos desde un navegador. Pues bien, una vez subido podemos ejecutar cualquier orden como:
https://dominio/path/script.php?command=orden
Pero como estarás pensando esto no es seguro. Lo que hice yo es meterlo en un directorio y en este meter un .htaccess para que sólo yo tuviera acceso.
Al final lo único que quería era poder usar git, así que me creé un shell script con wget para llamar a esta url. El script es tal que así:
#!/bin/bash
domain=»»
command=»wget -qO – \»http://$domain/commands/command.php?command=git $*\» | sed ‘1d’ | sed ‘\$d'»
echo «Dominio: $domain»
echo «Parámetros: $*»
eval $command
Ahora sólo hay que darle permisos de escritura y en mi caso lo he llamado rgit y lo he puesto en el path por comodidad. Esta sería una salida de la orden «rgit status -s«, en este caso un status limpio:
Dominio: www.dominio.com
Parámetros: status -s
Código de salida: 0
Salida de error:
Lo suyo es que el directorio .git con todo el ínidice esté fuera del htdocs del servidor, para ello se puede usar el parámetro –work-tree de git. Si por algún motivo no puede estar fuera podéis utilizar de nuevo un .htaccess para que nadie pueda entrar:
deny from all
Y con esto he conseguido un rodeo para poder usar una «shell» remota a través de un script PHP. Espero que os sea de ayuda.
Front-End vs Back-End
La experiencia de desarrollar una App Android en mi tiempo libre
Después de volver de Ecuador en donde estuve trabajando intensamente en un proyecto que me absorbía casi todo el tiempo decidí tomarme un descanso. En ese tiempo pensé en empezar a aprender a desarrollar apps en Android así que me puse a hojear la documentación oficial respecto al diseño y posteriormente empecé a hacer los ejemplitos que había en la documentación técnica. Entonces me dije, ¿por qué no intentas poner en práctica todo lo que vayas aprendiendo en una aplicación que tenga una utilidad real?, y así es como nació Peak Hour.
La primera versión era realmente sencilla pero me sirvió por un lado para aprender los conceptos básicos de Android (Activities, ciclo de vida de las mismas, tantear el IDE que por entonces decidí empezar con Eclipse aunque poco después migré a Android Studio, notificaciones, etc) y por otro tantear el mercado de apps y concretamente la de gestión de Pico y Placa y transporte en general. Estuve jugando con el código un par de meses o tres y para principios de 2015 ya tenía algo que más o menos funcionaba, el problema era que desde que había empezado a trabajar en Planeta Huerto no me quedaba mucho tiempo libre por lo que no fue hasta febrero de 2015 que presenté la app a mis compañeros de Ecuador.
La primera sensación fue decepcionante, a pesar que cuando estuve en Ecuador era muy cotidiano preguntarse entre los compañeros a quién le tocaba Pico y Placa, cuando se la envié a la gente de allí casi nadie la instaló, creo que no les parecía muy útil y eso me hizo replantearme si valía la pena seguir mejorándola. Después de este chasco la tuve medio abandonada durante unos cuantos meses, 5 o 6, en los que sólo hice un par de arreglos y poco más. En esos meses aproveché para hacer un par de cursos MOOC que me ayudaron mucho a entender como está diseñado Android, aprender muchísimo sobre todo de los patrones de diseño que utiliza el sistema, y detectar los problemas que tenía mi app y ver los errores que había cometido durante mi primer abordaje. Ahí es cuando dije, vamos a hacerlo un poco mejor y así también afianzas las cosas que has aprendido en los cursos. También me planteé que si quiero que la app sea utilizada masivamente tiene que ser más flexible y soportar las reglas de más ciudades a parte de Quito y así es como surgieró la versión 0.2 en las que se añadió el soporte multi-vehículo y la versión 0.3 en la que rediseñé completamente el manejo de reglas para que fuera muy sencillo añadir nuevas ciudades.
Estos dos cambios han resultado ser fundamentales, a partir de ese momento empezamos a crecer horizontalmente o lo que es lo mismo, se empezó a utilizar la aplicación en muchos otros sitios como Colombia, Brasil, Bolivia o Costa Rica, pero sobre todo en Colombia que es actualmente el mercado principal de la app. Es muy gratificante pensar que algo que tu has creado le está siendo útil a casi 300 personas, y eso es lo que te impulsa a seguir adelante. Ya os digo yo que por el dinero no es, de momento la app da para tomarse un poleo al mes y poco más, pero saber que toda esa gente no olvida su Pico y Placa y que seguramente se ha salvado de alguna multa gracias a la app, la verdad es que te alegra el día.
¿Y qué pasará con la app en el futuro?, pues de momento tengo planificados un par de cambios que ya tengo medio implementados y dependiendo de como vaya la cosa y si tengo tiempo hay muchas ideas en una libreta que parece que va siendo hora de ir sacándolas.
Ya os iré contando.