Blog

  • Algunas consideraciones de seguridad cuando se suben archivos vía PHP

    Algunas consideraciones de seguridad cuando se suben archivos vía PHP

    Php permite subir archivos vía HTTP de un modo bastante simple (Si tenés dudas consultá acá).

    Un uso bastante común de esta funcionalidad es la de permitir al visitante ingresar imágenes, por ejemplo: su foto de perfil.

    Existe una serie de consideraciones respecto de la seguridad a tener en cuenta cuando se realiza una tarea de este tipo.

    Con estas medidas estamos intentando evitar que un atacante engañe a nuestro sistema subiendo código malicioso que podría, por ejemplo, darle acceso a información privilegiada.

    Validar que el archivo recibido sea del tipo esperado

    Lo primero de lo que querremos estar seguros es de que el archivo que acabamos de recibir sea efectivamente una imagen (GIF, JPG, etc…). La forma inocente de hacer esta verificación es a través del nombre del archivo (si las últimas tres letras son…).

    La forma correcta de hacer esta verificación es a través del mime-type (Ver acá para más información).

    No almacenarlos en un directorio accesible públicamente

    En general, es conveniente que los archivos recibidos desde terceras partes (especialmente cuando se trata de visitantes), sean almacenados fuera del directorio raíz de nuestro proyecto.

    Desde un script de nuestro proyecto siempre se puede abrir un archivo con algo como:

    fopen(__DIR__.'/../uploads/foto.jpg');

    Contar con un método propio para ver su contenido

    Por último, es conveniente contar con algún método (puede ser un script especialmente diseñado para este efecto) que reciba como parámetro el nombre del archivo que se está solicitando y devuelva su contenido.

    Por ejemplo:

    showFile.php:
    
    <?php
    
    echo file_get_scontents($_GET['f']);

    De este modo, si alguien lograra de algún modo subir código malicioso, al intentar ejecutarlo se encontraría con que en su navegador se vería su propio código (sin haber sido ejecutado nada).

  • Cómo tratar con procesos largos en PHP

    Cómo tratar con procesos largos en PHP

    Antes de meternos en los detalles distingamos dos escenarios:

    1. PHP dentro del contexto de un WebServer
    2. PHP como lenguaje de scripting de algún proceso off-line.

    Cuando se trata del segundo caso, es posible que existan oportunidades de mejorar el tiempo que insume el proceso, pero, en la gran mayoría de los casos, no pasará de ser una pequeña molestia si no se consigue este objetivo.

    Cuando estamos en el contexto de WebServer, la molestia puede ser tal que haga que nuestros visitantes abandonen el sitio (Para no regresar jamás).

    Por otro lado, es de suponer que en un ambiente web la concurrencia es alta (Es decir, un script PHP que está ejecutando está compitiendo contra muchos otros similares a él por el uso de los recursos), con lo cual, el propio sistema suele tomarse algunos recaudos para evitar que muchos inocentes sufran por los desmanes de unos pocos alborotadores :).

    Uno de los límites que se nos impone (desde el archivo php.ini) es el tiempo máximo de ejecución (Que normalmente está en los 30 segundos).

    Pero eso es lo que el servidor soporta antes de determinar que nuestro script tarda demasiado… los usuarios reales tienen mucha menor tolerancia (Hay estudios que afirman que una demora de más de 4 segundos hace que el 75% de los visitantes pierdan la paciencia…).

    Entonces… ¿cómo atacar este problema?

    Como diría Zun Tzu, la mejor manera de salir vivo de una batalla es no entrar nunca (No sé si eso es exactamente lo que dijo, pero si no, seguro que pensaba algo parecido :)).

    Llevado al mundo de la programación web, la primera pregunta que debe hacerse es: ¿es realmente necesario ejecutar este proceso consumidor de tiempo?. Aunque parezca una trivialidad, en muchas ocasiones la respuesta es un rotundo NO, y simplemente se hace por razones que pueden haber sido válidas tiempo atrás pero ya no lo son más.

    La siguiente pregunta (Asumiendo que la respuesta a la primera haya sido SI) es: ¿es realmente necesario ejecutar este proceso ahora mismo?. Esta es una pregunta un poco más sutil, pero sumamente importante. Para responderla hay que pensar mucho sobre lo que significa «ahora mismo»: el momento en que se está ejecutando PHP en un WebServer es cuando se ha recibido una petición de un usuario y se está intentando generar una respuesta.

    Aquí nos metemos un poco en temas de psicología más que de programación, pero vale la pena intentarlo: muchas veces un usuario preferirá una respuesta rápida y casi correcta (o que parezca correcta) antes que una respuesta perfecta pero retrasada.

    Se puede pensar en esto como en un truco de magia (un acto de ilusionismo si se quiere), donde es más importante lo que se ve que lo que efectivamente sucede.

    Un típico ejemplo de estos problemas los constituye el recálculo de contadores. Tomo a Facebook como ejemplo, si te fijás en los números que indican la cantidad de actualizaciones no leídas podrás notar que rara vez es correcto… sin embargo, ¿cuál es el riesgo de tener un número ligeramente diferente del real? ¿estarías dispuesto a esperar más para tener la tranquilidad de que el número es correcto?

    En la mayoría de los casos, con que eventualmente los números cierren no habrá mayores problemas, lo cual da lugar a un esquema de solución muy utilizado: diferir la ejecución de procesos largos.

    ¿Cómo se logra esto? Una forma artesanal de hacerlo es guardar en algún medio de almacenamiento (por ejemplo una base de datos), toda la información necesaria para realizar el cálculo en cuestión, devolver al usuario algo que le de tranquilidad y, mediante algún mecanismo offline (un cronjob por ejemplo), terminar los trabajos que se dejaron a la mitad.

    Otro modo de resolverlo (un poco más profesional) es utilizar algún sistema de procesamiento de trabajos en paralelo, por ejemplo Gearman.

    ¿Qué otras alternativas se te ocurren para resolver este problema?

  • Cómo probar tus scripts PHP sin instalar un intérprete

    Cómo probar tus scripts PHP sin instalar un intérprete

    No sé si te pasará lo mismo, pero para mi, la posibilidad de escribir (y probar) código sin necesidad de tener mi propia computadora a mano es muy seductora.

    He probado CodeAnyWhere y está bastante cerca de lo que me gustaría, pero todavía (2017) le falta un poco… imagino que para 2020 será la opción de facto… por el momento hay que conformarse con opciones un poco menos sofisticadas (o llevar la compu a cuestas… lo que prefieras).

    Pero bueno, cuando se trata de tirar algún comando rápido, hacer alguna prueba de concepto o simplemente matar unos minutos libres, acá te dejo algunas opciones interesantes:

    Run Write PHP Online

    Una interfase muy bonita, bien pulida y, lo mejor, interpreta mientras escribís y te da la salida (o el error) inmediatamente.

    (Me comenta mi amigo @MySelfCoding que este no va más… una pena :'( )

    WritePHPOnline

    Un poco menos profesionale que el anterrior, la interfase no es tan limpia, pero bueno… cumple con su cometido.

    Tiene un lindo cheatsheet de funciones php que puede venirte bien.

    PHPFiddle

    Esta es una opción que no conocía, por lo que se ve, parece querer ser un competidor de CodeAnywhere… aunque está bastante lejos de lograrlo… para investigarlo un poco.

    PHPTester

    También, una herramienta algo rústica, pero que cumple.

    Permite elegir la versión del intérprete.

    RunPHPOnline

    Muy similar a PHPTester, con la UI algo más pulida.

    ¿Qué otras opciones conocés para testear código PHP rápidamente?

  • Cómo debuggear un comando Symfony usando PhpStorm

    Cómo debuggear un comando Symfony usando PhpStorm

    En este post voy a mostrarte un caso algo particular de cómo debuggear un script que corre por línea de comandos.

    Se trata de debuggear un script hecho con el framework Symfony.

    La particularidad que tiene este escenario es que el código que escibiste (y que querés verificar), no es un archivo php común, si no que es una claseque extiende de ContainerAwareCommand, con lo cual, no es posible invocarla en forma directa.

    La ejecución de este comando requiere del paso por el script bin/console. Ahora, si te fijás su contenido notarás que no es más que un script php, con lo cual, podría ser debuggeado usando la configuración «estándar» de PhpStorm para estos casos…

    La idea en definitiva es simple, cuando ejecutás algo como:

    php bin/console miApp:miComando

    El script php que estás ejecutando es bin/console y «miApp:miComando» no es otra cosa que un argumento de CLI.

    Entonces precisamente, de esa forma es como tenés que configurar el IDE para que pueda ejecutar tu comando (Y puedas ponerle breakpoints, evaluar variables, etc…):

    En este ejemplo, el comando que yo uso (EnviarRecordatorios) recibe parámetros a su vez. Ningún problema, son más argumentos que se le pasan a bin/console.

    ¿De qué otra forma podrías debuggear comandos symfony?

  • Cómo debuggear un script de CLI con XDebug y PhpStorm

    Cómo debuggear un script de CLI con XDebug y PhpStorm

    Es muy común encontrarse con la necesidad de escribir scripts que deberán ser ejecutados por la línea de comandos dentro del contexto de una aplicación web, cronjobs por ejemplo.

    Hasta hace poco tenía muy claro cómo debuggear un script que ejecutaba a través del webserver, pero no había logrado (y francamente, no creía que fuera posible) debuggear un script que corría desde el CLI.

    Buscando un poco (y haciendo algo de prueba y error) finalmente lo logré.

    Si usás PhpStorm (y si no lo hacés aún, te lo recomiendo ampliamente) estos son los pasos que deberás seguir:

    Para empezar, asegurate de tener XDebug o ZendDebugger instalado en el entorno donde vas a correr tu script (En mi caso, usé una máquina virtual que ya tenía todo lo necesario).

    Después, la clave del tema está en el concepto de Run/Debug configuration:

    En este cuadro de diálogo:

    Debés indicar qué archivo vas a querer debuggear y, eventualmente, qué argumentos vas a querer pasarle al script al momento de ejecutar.

    Una vez que tengas la configuración armada… ¡listo! Ya podés ver la ejecución de tu script paso a paso como lo harías con una aplicación web.

    ¿Cómo debuggeas tus scripts?

  • Cómo autenticar usuarios en una aplicación web con PHP

    Cómo autenticar usuarios en una aplicación web con PHP

    Este es un tema que suele causar bastante confusión en la gente que se enfrenta con este problema por primera vez… hay tantos usuarios/passwords/niveles de autenticación que si no se presta mucha atención es fácil perderse.

    Lo principal es entender que la autenticación es un proceso de comunicación entre dos entidades:

    1. Un cliente
    2. Un servidor

    El cliente es el que se identifica (generalmente utilizando un par «nombre de usuario» + «contraseña») y el servidor es quien valida esas credenciales y devuelve algún tipo de identificador de acceso.

    Podríamos pensarlo como el guardián de una discoteca en una fiesta privada. Cualquiera puede pararse ante el grandote y decirle que es uno de los invitados, pero si tu nombre no figura en la lista… por más que patalees, te vas a quedar afuera (Y aún si tu nombre figura, si te olvidaste el DNI… más vale pegar la vuelta).

    En el caso de una aplicación web, existen muchos clientes y servidores interviniendo (De hecho, como vas a ver en breve, varios de estos servidores son a la vez clientes… ¡como para no confundirse!).

    En el clásico esquema de un request:

    El primer cliente que aparece es el browser (FireFox, Chrome, IE, etc…) y el servidor (En este post me voy a referir a «cliente» y «servidor» en su sentido como procesos, no como computadoras) es el webserver (Apache, NginX, etc…).

    Entonces, el primer nivel de autenticación que debe superarse es este: el cliente que se conectó al webserver ¿presentó credenciales válidas?

    Hoy en día es extremadamente raro encontrarse con este tipo de autenticación (por lo general, los servidores web están configurados de modo de aceptar conexiones de cualquier cliente sin pedir demasiado, pero se puede configurar este tipo de autenticación).

    Una vez que el webserver dió la bandera verde, dependiendo de cuál haya sido el pedido del cliente, se le enviará una respuesta (generalmente un texto HTML).

    El siguiente nivel de autenticación es el del webserver contra el servidor de base de datos:

    Desde el punto de vista del servidor de base de datos, quien hace la conexión es el cliente (Es indiferente si se trata de una acción iniciada por un humano o por una computadora… en última instancia, la comunicación siempre es computadora-a-computadora…).

    Entonces acá tenemos:

    1. Un cliente del webserver (el navegador)
    2. Un cliente del servidor de bases de datos (el webserver)

    Al igual que en el ejemplo anterior, el cliente (en este caso el webserver), debe proveer de credenciales para que el servidor de bases de datos le permita acceder a sus servicios.

    Es importante notar que las credenciales que utiliza el navegador para autenticarse ante el servidor web no tienen por qué ser las mismas que usa el webserver para conectarse a la base de datos (De hecho, lo más probable es que sean completamente diferentes).

    Hasta ahora te mostré los niveles más bajos de autenticación (Los que podríamos llamar de infraestructura), pero existe un tercer nivel de autenticación: el de la aplicación.

    En este nivel es responsabilidad del propio sistema (es decir tuya :)) decidir quién puede ingresar y qué puede hacer una vez adentro.

    Pueden usarse diversos mecanismos para lograr este tipo de autenticación: el más simple (y común) es el almacenamiento de nombres de usuario y contraseñas en una base de datos a la que la aplicación tiene acceso. Otro método más elaborado es el uso de servicios de terceros (Google, Facebook, Twitter, etc…).

    Entonces, recapitulando…

    Cuando te enfrentás a algo como esto:

    Lo que estás viendo es el resultado de la interpretación de HTML por parte de tu navegador.

    Los datos que ingreses ahí van a ser recibidos primero por algún webserver y luego, a través de algún script (PHP por ejemplo), contrastados contra alguna base de datos (A la cual el script accederá utilizando sus propias credenciales).

    Es por eso que, por lo general, una aplicación php tenga su propio username definido en su servidor de base de datos, aunque tenga un gran número de usuarios propios (visitantes registrados).

    ¿Te quedó alguna duda? ¡Espero tus comentarios!

  • Cómo autenticar usuarios con redes sociales en PHP

    Cómo autenticar usuarios con redes sociales en PHP

    Algo que se ha puesto bastante de moda últimamente es la posibilidad de logearse en un sitio cualquiera usando un usuario creado para otro (Por ejemplo, logearte a StackOverflow usando tu Gmail o a Clarin usando tu Facebook).

    Este enfoque presenta varias ventajas:

    1. Para el usuario significa no tener que inventar (¡y recordar!) una contraseña más y, por si eso fuera poco, ingresar a tu sitio haciendo un solo click.
    2. Para el sitio significa no tener que almacenar información de usuarios ni hacer un doble-opt-in (Se asume que el proveedor de autenticación ya ha validado la identidad del usuario).

    Ahora bien, desde el punto de vista de tu aplicación… ¿cómo podés implementar esto?

    La mayoría de los grandes proveedores de autenticación (Gmail, Facebook, Twitter, etc…) utilizan un protocolo que se conoce como OAuth, muy seguro pero algo complejo de implementar a mano.

    Afortunadamente existen algunas librerías que hacen el trabajo sucio por nosotros. Veamos algunas:

    HybridAuth

    Esta librería (Puede consultarse la documentación acá) ofrece muchas posibilidades además del login (Compartir en redes sociales, acceso a perfiles, etc…).

    Como de costumbre, el uso recomendado es mediante Composercomposer init y después (si no incluiste la dependencia interactivamente) composer require hybridauth/hybridauth

    En definitiva, el archivo composer.json debería quedar similar a:

    {
     "name": "leeway/hybrid_auth",
     "description": "Test de hybrid_auth",
     "require": {
     "hybridauth/hybridauth": "^2.10"
     },
     "authors": [
     {
     "name": "Mauro Chojrin",
     "email": "mauro.chojrin@leewayweb.com"
     }
     ]
    }

    Luego, instalamos las dependencias usando composer install y estamos listos para comenzar nuestra aplicación.

    HybridAuth provee una clase principal: Hybrid_Auth.

    Lo primero que vamos a necesitar hacer es, obviamente, crear una instancia de esta clase. El parámetro que recibe el constructor es la configuración.

    Esta configuración tiene una cantidad de parámetros, algunos opcionales y otros obligatorios. Los básicos son:

    • base_url URL a donde el proveedor (Google, Facebook, Twitter, etc…) redireccionará una vez realizada la autenticación. A esta URL se la conoce como callback
    • providers Lista de proveedores que quieras usar (¡Claro que deben estar soportados por la librería!).
      • enabled true o false
      • keys Credenciales de acceso para tu aplicación:
        • id Identificación de tu aplicación
        • key Clave de acceso
        • secret Clave secreta

    Las credenciales de acceso las debes generar en cada proveedor (Puedes ver cómo hacerlo para Facebook siguiendo este enlace, para Google este y para Twitter este).

    Veamos un ejemplo:

    <?php
    
    return [
            'base_url' => 'http://localhost:8080/vendor/hybridauth/hybridauth/hybridauth/',
            'providers' => [
                            'Facebook' => [
                                    'enabled' => true,
                                    'keys' => [
                                            'id' => 'XXXX',
                                            'secret' => 'YYYY',
                                    ]
                            ]
                    ],
    ];

    Aquí lo importante es (más allá de la identificación de mi app en particular), la dirección a la que Facebook (o el proveedor de autenticación) deberá realizar su callback.

    En mi caso es una dirección que comienza con http://localhost:8080 porque estoy desarrollando una prueba de concepto usando el servidor embebido en PHP, si fuera un sitio productivo habría que escribir el dominio.

    Sin entrar en los detalles de OAuth (U OpenID que a los efectos de este artículo no distan mucho), el circuito de autenticación implica dejar por un momento nuestro sitio para pedirle al usuario que realice un login en otro y, una vez logrado esto, vuelva.

    Toda esta complejidad precisamente la maneja HybridAuth a través del archivo vendor/hybridauth/hybridauth/hybridauth/index.php cuyo contenido no es más que:

    <?php
    /**
    * HybridAuth
    * http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
    * (c) 2009-2015, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
    */
    
    // ------------------------------------------------------------------------
    //      HybridAuth End Point
    // ------------------------------------------------------------------------
    
    require_once( "Hybrid/Auth.php" );
    require_once( "Hybrid/Endpoint.php" );
    
    Hybrid_Endpoint::process();

    Obviamente toda la magia está en el método Hybrid_Endpoint::process() el cual, una vez validada la autenticación, volverá a redirigir al visitante hacia la página en la que ésta se solicitó.

    En mi ejemplo sería el archivo login.php:

    <?php
    
    require_once __DIR__.'/vendor/autoload.php';
    
    session_start();
    $config = require_once 'config.php';
    
    $ha = new Hybrid_Auth( $config );
    
    try {
            $facebook = $ha->authenticate( 'facebook' );
            $user_profile = $facebook->getUserProfile();
    
            echo 'UserProfile: '.print_r($user_profile, 1);
    } catch ( Exception $e ) {
            echo $e->getMessage();
    }
    

    Al cual se accede desde login.html:

    <html>
            <form>
                    <fieldset>
                            <legend>Identif&iacute;cate con tu Facebook</legend>
                                <a href="login.php">Autorizar</a>
                    </fieldset>
            </form>
    </html>
    

    ¿Quedó alguna duda? ¡Espero tus comentarios!

  • Cómo autenticar usuarios vía HTTP usando PHP

    Cómo autenticar usuarios vía HTTP usando PHP

    La autenticación a nivel de HTTP se activa mediante la configuración del webserver.

    Es el nivel más bajo de autenticación que puede tenerse en un entorno web, ya que lo que va a verificar es que el cliente que solicita un determinado recurso (URI) tenga acceso a él, antes de hacer ningún otro tipo de verificación.

    De lo que estoy hablando es de lo que sucede cuando querés ingresar a un sitio, por ejemplo http://localhost y, en lugar de ver el contenido del sitio, se abre una ventana como esta:

    Por lo general, no es mucho lo que puede validarse (No hay posibilidad de ofrecer diferentes niveles de acceso ni nada parecido), con lo cual, no es algo que suela utilizarse en entornos de acceso público.

    La forma de configurar este tipo de acceso depende del web server que uses.

    En el caso de Apache, la forma de lograrlo es:

    1. Crear un archivo de autenticaciones (Usando la utilidad htpasswd por ejemplo).
    2. Dentro de la configuración del servidor, definir un bloque para el DocumentRoot:
     <Directory "/var/www/html">
       AuthType Basic
       AuthName "Restricted Content"
       AuthUserFile /etc/apache2/.htpasswd
       Require valid-user
     </Directory>
    1. Reiniciar el servidor (O, menos drástico, recargar la configuración).

    A partir de este momento, cualquier usuario que desee ingresar a tu sitio tendrá que identificarse (Ante el webserver).

    Otra forma de usar este tipo de autenticación (que no depende de la configuración del webserver), es hacerlo a través de PHP:

    La clave aquí es el uso de la función header (y conocer algunos detallitos del protocolo HTTP :)).

    Básicamente se trata de un script que será invocado dos veces:

    La primera será la que solicite las credenciales y la segunda será la que valide (Lo mismo que podrías hacer si hicieras un login clásico, con la diferencia de que la segunda llamada se produce automáticamente al completar los datos).

    El código es este:

    <?php
    if (!isset($_SERVER['PHP_AUTH_USER'])) {
        header('WWW-Authenticate: Basic realm="My Realm"');
        header('HTTP/1.0 401 Unauthorized');
        echo 'Este texto se ve si el usuario cancela';    
    } else {
        echo "<p>Hola {$_SERVER['PHP_AUTH_USER']}.</p>";
        echo "<p>Tu password es {$_SERVER['PHP_AUTH_PW']}.</p>";
    }

    El if está para validar si estás en la primera llamada o en la segunda. Las claves de la variable de $_SERVER se completan automáticamente con lo ingresado por el usuario.

    Esta forma puede ser más conveniente ya que te permite independizarte del WebServer con el que estás trabajando (Y por lo tanto, cambiarlo será más sencillo).

    Por último, una forma de acceder al sitio sin pasar por el formulario es pasar las credenciales como parte de URL:

    http://user:password@localhost

    ¿Qué forma de autenticación usas en tus aplicaciones?

  • Cómo guardar una imagen en una base de datos

    Cómo guardar una imagen en una base de datos

    Un clásico problema de una aplicación web es el almacenamiento de archivos subidos por los usuarios (Sus fotos por ejemplo).

    Si bien teóricamente se puede realizar sin mayores inconvenientes (Al fin y al cabo, un archivo digital no es más que una colección de datos binarios), es sumamente ineficiente hacerlo.

    Veamos cómo sería esto:

    Primero que nada, habría que manejar de alguna forma el upload de archivos, pero, asumiendo que el archivo ya está disponible para php se podría pensar en almacenarlo dentro de la base de datos utilizando algún campo tipo BLOB.

    Un problema inmediato que surge de tomar esta opción es que la base de datos crecerá mucho si el sistema es muy utilizado, lo cual impactará negativamente en su rendimiento, hará más costozos los backups, etc…

    Una alternativa simple es guardar, en lugar del contenido del archivo, su localización (Puede ser la ruta al archivo, si está guardado en algún medio de almacenamiento, ya sea el disco local o alguno externo, como S3 por ejemplo).

    De esa forma se logra aislar a la base de datos del manejo de información que, por otro lado, tampoco será sencilla de consultar y, a la vez, permite aprovechar capacidades del medio de almacenamiento elegido (Incluso hace mucho más simple la introducción de alguna capa de caché como ser un CDN).

    Si lo que buscas es realizar búsquedas dentro del contenido de archivos de texto, lo mejor que puedes hacer es usar alguna otra herramienta como Solr, ElasticSearch o Sphinx (Por nombrar sólo algunos).

    Si, de cualquier forma decides guardar el contenido del archivo directo en la base de datos, te recomiendo guardarlo con alguna forma de codificación que prevenga problemas con los caracteres especiales (acentos, eñes, etc…), por ejemplo base64 o algún formato comprimido (Zip por ejemplo).

    En general diría que los datos que se almacenan en la base deberían ser (al menos en su gran mayoría) de naturaleza dinámica (Es decir, que pueden cambiar a lo largo del tiempo). Aquellos datos que permanecerán estáticos probablemente tengan un mejor lugar donde residir.

    Por último, ¿pensaste en cómo mostrarías la foto si lo que está guardado en la base es el contenido del archivo en lugar de su ruta?.

    En el caso de que tomes mi sugerencia es bien fácil, basta con algo como:

    <img src="<?php echo $usuario['foto']; ?>"/>

    Si en cambio lo que está guardado en la base es el contenido del archivo… no es que sea imposible, claro, pero seguro que es algo más complicado (Tal vez tengas que hacer un script que devuelva los datos binarios de la foto o algo así)… ¿para qué hacer las cosas más difíciles de lo que debe ser?

  • Cuál es el mejor hosting para PHP y Mysql

    Cuál es el mejor hosting para PHP y Mysql

    Tu aplicación está lista para abrirla al mundo, ¡felicitaciones!

    Ahora hay una pregunta ineludible: ¿dónde la vas a alojar?

    Es tentador usar un hosting compartido y que otro se encargue de la infraestructura, ¿no? Más aún si es gratuito… pero ¿qué pasa cuando se necesita algo más?

    No es para nada raro enfrentarte a situaciones como estas:

    «Tengo una aplicación muy sencilla alojada en hostinger. Iba bien hasta ayer que se cayó la web y resulta que tengo un ataque DDos y claro no puedo monitorear ni nada por que no tengo acceso ssh al servidor«


    «Mi proveedor de hosting me ha bloqueado todo acceso al cpanel y página web por tener el disco lleno, ahora me obliga a adquirir un plan superior para darme acceso al cpanel»


    «Durante meses estuvo funcionando bien hasta que los que me proveen el servicio de hosting se les ocurrio cambiar el servidor, a partir de ahí las variables $_SESSION llegan vacias a las otras paginas.»

    Claro que montar tu propio servidor tampoco es un paseito.

    Lo primero que tenés que pensar en esto es si vas a ser capaz de darle soporte (Qué pasa si se cae el Apache en la mitad de la noche por ejemplo).

    Después está el tema de qué le vas a instalar.

    ¿Sos un fanático del composer?

    ¿Necesitás Memcached?

    ¿APC?

    ¿Cronjobs?

    Otro tema importante es qué consumo de recursos tiene tu aplicación.

    ¿Qué tanto tráfico vas a tener?

    ¿Qué tanta memoria necesitan tus scripts para correr cómodamente?

    Como de costumbre, no existe una respuesta única y universal, cada alternativa tiene sus ventajas y desventajas.

    Ventajas de usar un servidor compartido

    1. Costo (El abono suele ser más económico, aunque algunas VPS como DigitalOcean tienen planes super interesantes)
    2. Soporte técnico incluido (Como siempre, no todos los proveedores te van a dar el mismo nivel de soporte, pero siempre vas a tener algún tipo de soporte ante inconvenientes)
    3. Actualizaciones a cargo del proveedor (No te vas a tener que preocupar por actualizar paquetes)

    Desventajas de usar un servidor compartido

    1. Actualizaciones a cargo del proveedor 🙂 (No, no es un chiste, si bien esto te libera de responsabilidad, te resta flexibilidad ya que para instalar cualquier paquete vas a tener que pedir permiso… ¡y puede ser que te lo nieguen!)
    2. Disponibilidad de recursos errática (Dependés de qué tan bien o mal se comporte el resto de las aplicaciones que compiten con la tuya por el uso de los recursos compartidos lo cual puede impactar negativamente en la experiencia de tus usuarios)
    3. Dificultad para ajustar la configuración de php (No siempre tendrás acceso a modificar el archivo php.ini por ejemplo).

    VPS o hosting compartido: cómo decidir

    Salvo que te encuentres en alguna de estas situaciones:

    • Tu proyecto es muy chicos
    • Tu sitio es mayormente estático
    • No sabés (ni querés aprender) cómo administrar un webserver con algún esquema de monitoreo automatizado

    La mejor opción será siempre ser dueño de tu servidor, aunque implique algo más de trabajo al comienzo, instalando una herramienta como monit vas a poder dormir tranquilo 🙂

    Así que ya sabés, en tu próximo proyecto, dale una oportunidad al VPS.

    De hecho, si no tenés mucha experiencia administrando tus propios servidores, un proveedor que puede resultarte sumamente interesante es Cloudways que ofrece un modelo híbrido:

    Para una gran cantidad de cosas se comporta como un hosting compartido, en el sentido de las herramientas simples que te brinda, pero en realidad opera como un VPS, o mejor dicho, como varios a la vez.

    Usando Cloudways podés tener un sistema multicloud a muy bajo costo y con muy poco esfuerzo de administración.

    Vale la pena conocerlo. Probalo.