Categoria: Flash Remoting (10 articulos)
February 27, 2006

setCredentials con Base de Datos

Algo que he notado en ocasiones, es que la gente tiene una cierta confusión a la hora de querer mezclar setCredentials con Base de Datos. Veamos un ejemplo mas claro usando MySQL. Antes de comenzar, seria bueno que se leyeran este par de entradas del blog :

Autentificación de usuarios con FlashRemoting y setCredentials

Uso de herencia en AMFPHP en conexiones a bases de datos


Ya con esta información en nuestra mente, procedamos. En primer lugar, veamos nuestra clase Config.php la cual nos ayuda a tener mejor organizadas nuestras conexiones a MySQL :

class Config {
   
    //-------------------------
    //Configuraciones MySQL
    var $dbhost = "localhost";
    var $dbname = "noticias";
    var $dbuser = "root";
    var $dbpass = "";
    //-------------------------
   

    function Config ($db) {
        if(basename($_SERVER['PHP_SELF']) == "Config.php") exit; //Esta línea es para evitar que accedan al archivo de manera pública.
        $this->conn = $this->connect($db);
    }

    function connect ($db) {
        if(!$conn = @mysql_pconnect($this->dbhost, $this->dbuser, $this->dbpass)) {
            return false;
        }
        if (!@mysql_select_db ($db, $conn)) {
            return false;
        }
        return $conn;
    }
   
    function log ($log) {
         $file = implode("", file("log.txt"));
         $open = fopen ("log.txt", "w+");
         $file .= date ("\l\o\g :::: d/m/Y h:m:s ----> ", time()).$log."\n";       
         fwrite ($open, $file);
         fclose ($open);
     }
    function _authenticate ($user,  $pass) {
         $user = addslashes($user); //escapamos las comillas para evitar un MySQL inyection...es por seguridad.
         $pass = addslashes($pass);
         $query = "SELECT `roles` FROM `users` WHERE `user` LIKE '".$user."' AND `password` LIKE '".$pass."';";
         $result = mysql_query ($query, $this->conn);
         if ($data = mysql_fetch_assoc($result)) {
              return $data['roles'];
         } else {
              return false;
         }

 }
}

Todo lo anterior, ya está explicado en uno de los links (a excepción del nuevo _authentificate que hemos creado), así que no es necesario repetir . Por otro lado, veamos nuestro servicio seguro :


include_once("Config.php");

class News extends Config {

     function News {
          parent::__construct($this->dbname);//Esta linea llama al constructor de la clase.
          $this->methodTable = array (
               "getNews" => array (
               "description" => "Devuelve el listado de noticias",
              "access" => "remote",
              "roles" => "admin",
               "arguments" => array ()
               )
          );
     }

     function getNews () {
          return "AsFusion es un blog mas en la blogosfera que intenta sobrevivir en este mundo cruel";
     }
}

Como verán, está mi clase News la cual hereda los métodos y propiedades de mi clase Config. Entre lo heredado, está obviamente mi método _authenticate el cual me validará a mi usuario en una supuesta tabla como esta :

user
password
roles
daniel
asfusion
admin
nahuel
coldfusion
admin


Básicamente mi método _authenticate me validará el usuario haciendo una consulta a la base de datos, y devolverá el rol de nuestro usuario seleccionado. Si este rol concuerda con lo especificado dentro de nuestro methodTable, se validará correctamente el usuario. No es díficil esto de combinar setCredentials con MySQL....solo se trata de aplicar un poco de lógica si es que antes hemos combinado FlashRemoting con Base de Datos. Este seria el código de Actionscript :

import mx.remoting.Service;
import mx.services.Log;
import mx.rpc.RelayResponder;
import mx.rpc.FaultEvent;
import mx.rpc.ResultEvent;
import mx.remoting.PendingCall;

var sSecured:Service = new Service ("http://localhost/gateway.php", null,"News",null,null);
sSecured.connection.setCredentials ("daniel", "asfusion");

function welcomeResult (rs:ResultEvent) {
     trace (rs.result);
}

function welcomeFault (fl:FaultEvent) {
     trace("Su usuario no esta validado");
     trace("Hubo un problema: "+fl.fault.faultstring);
     trace("El código del error es: "+fl.fault.faultcode);
     trace("Detalles: "+fl.fault.detail);
}

var pcWelcome:PendingCall = sSecured.welcome ();
pcWelcome.responder = new RelayResponder (this, "welcomeResult", "welcomeFault");


Algo a destacar, es que también si queremos agregarle un poco más de seguridad a nuestra aplicación, podemos encriptar el password en la base de datos usando md5. Entonces nuestra validacioón quedaría así :

    function _authenticate ($user,  $pass) {
         $user = addslashes($user); //escapamos las comillas para evitar un MySQL inyection...es por seguridad.
         $pass = md5($pass); //Encriptamos el password previamente.
         $query = "SELECT `roles` FROM `users` WHERE `user` LIKE '".$user."' AND `password` LIKE '".$pass."';";
         $result = mysql_query ($query, $this->conn);
         if ($data = mysql_fetch_assoc($result)) {
              return $data['roles'];
         } else {
              return false;
         }

     }

Espero haber aclarado un poco más este tema, y que esto sea de gran ayuda a cualquiera que desee enfocarse plenamente a FlashRemoting.

Saludos¡

February 21, 2006

Un error en el articulo anterior con el método log() de la clase Config.

Bueno, revisando mi código, encontré un pequeño bug en un método llamado log de mi clase Config que utilizo para ir guardando información de como se comportan mis servicios en el lado del servidor. Basicamente provocaba un doble salto de linea que hacia que el archivo de log.txt se duplicará exponencialmente llegando a alentar muchísimo los scripts. Debería quedar así :

    function log ($log) {
         $file = implode("", file("log.txt"));
         $open = fopen ("log.txt", "w+");
         $file .= date ("\l\o\g :::: d/m/Y h:i:s ----> ", time()).$log."\n";       
         fwrite ($open, $file);
         fclose ($open);
     }

Saludos!
January 04, 2006

Uso de herencia en AMFPHP en conexiones a bases de datos.

Esto es algo que he venido queriendo escribir desde hace rato....ahora aprovecho la oportunidad de que ando desarrollando una miniaplicación que me permita elaborar las facturas mas fácilmente (odio llenar los campos a mano en word). Básicamente lo que hace este desarrollo es llevar un registro de los clientes con los que trabajo (son sus respectivos datos como clave de factuación y domicilio), el tipo de trabajo realizado y algunas cotizaciones que yo pueda modificar. La ventaja es que me hace el desglose de impuestos automáticamente. Como se imaginarán (por el título) uso una base de datos que es MySQL. La situación es que, como muchos sabrán, cuando han manejado conexiones de bases de datos en una página, es muy práctico crear un típico archivo que se suele llamar config.php donde tenemos las conexiones y contraseñas. En AmfPhp como bien sabrán construimos nuestros servicios a base de clases de PHP. Y si son clases, porque no usar herencia? Ya habia comentado algo de herencia en AmfPHP en este tutorial pero aquí lo extenderemos a conexiones a bases de datos.

Básicamente este es el codigo que suelo usar para mi clase Config que esta dentro de un archivo llamado Config.php.

<?PHP
class Config {
   
    //-------------------------
    //Configuraciones MySQL
    var $dbhost = "localhost";
    var $dbname = "facturacion";
    var $dbuser = "root";
    var $dbpass = "";
    //-------------------------
   

    function Config ($db) {
        if(basename($_SERVER['PHP_SELF']) == "Config.php") exit; //Esta línea es para evitar que accedan al archivo de manera pública.
        $this->conn = $this->connect($db);
    }

    function connect ($db) {
       
        if(!$conn = @mysql_pconnect($this->dbhost, $this->dbuser, $this->dbpass)) {
            return false;
        }
        if (!@mysql_select_db ($db, $conn)) {
            return false;
        }
        return $conn;
    }
   
    function log ($log) {
         $file = readfile("log.txt");
         $open = fopen ("log.txt", "w+");
         $file .= date ("\l\o\g :::: d/m/Y h:m:s ----> ", time()).$log."\n";       
         fwrite ($open, $file);
         fclose ($open);
     }
   
}
?>

Si se leen detenidamente el código, creo unas propiedades al inicio de Config donde estan mis configuraciones de la base de datos. Dentro de la función constructora hago la conexión ademas de agregar una pequeña línea de seguridad. Ahí mismo verán que requiero como argumento el nombre de la base de datos y guardo el id de la conexión, aún a pesar de que la defino previamente como propiedad. Esto es porque en ocasiones en un projecto grande hacemos conexiones a mas de una base de datos. Esto me da la posibilidad de que en un servicio diferente sobreescriba la propiedad $dbname y todo siga funcionando correctamente. Mas adelante ustedes verán la función de connect (no tiene mucha ciencia si ya saben combinar PHP con MySQL) y otra llamada log la cual me ha llegado a resultar ser muy útil a la hora del debugeo del lado de AMFPHP. Muchos sabrán que cuando usamos remoting tenemos al NetConection Debugger para depurar la aplicación del lado de Flash....pero no tenemos nada del lado del servidor, por eso creo esa función que me permite llevar un cierto registro. Ahora en nuestro servicio hijo hacemos lo siguiente :


<?PHP
include_once ("Config.php");

class Billing extends Config {

    function Billing () {
         parent::__construct($this->dbname);//Esta linea llama al constructor de la clase.
         $this->methodTable = array (
                     "getClients" => array (
                         "description" => "Get the client list from db.",
                        "access" => "remote",
                        "arguments" => array ()
                     )
             );
    }
   
   
    //Metodos
    /*-----------------------------------*/   
    function getClients () {
        $query = "SELECT `client` AS label, `id` AS data, `address`, `rfc` FROM `clients` ORDER BY `client`;";
        $this->log($query);//Uso el método heredado log para hacer debugeos
        return mysql_query($query, $this->conn);
    }
   
   
}
?>

Lo primero que hacemos primero es incluir el archivo Config.php y después establecemos la herencia con la palabra reservada extends. Además, si ven dentro de la función constructora de Billing hay una línea como esta :

         parent::__construct($this->dbname);

Esta línea lo que hace es llamar a la funcion constructora de la superclase donde establecemos la conexion de la base de datos creandonos automáticamente la propiedad $conn que es muy importante para que si en un mismo servicio usamos dos bases de datos, podamos crear una conexion temporal en algún método (por eso dejo que la función connect heredable dentro de Config). También verán que dentro de getClients uso el método log que definí en la superclase Config. No es necesario usar ese método ahí, pero sirve para ilustrar el uso que se le puede dar.

En fin, este es todo el tutorial...la idea es proveer una solución mas elegante a las conexiones de bases de datos en remoting...por ahí he visto otras maneras usando constantes definidas en un archivo config.php pero nunca he han gustados. Espero que les sirva a algunos. Saludos!

July 25, 2005

Trio Motor un ejemplo de una aplicación hecha con Remoting

Trio Motor

Este ejemplo lo he tenido en mi disco duro hace mas de un año y ha estado bastante olvidado. Lo hice cuando salió la nueva versión de flash remoting y en su momento iba a ser la segunda parte de un tutorial para Devnet, pero nunca llego a terminarse. Si bien ya tiene un tiempo creo que seria una pena que termine olvidado en mi disco duro por eso he decidido hacerlo publico.

En esta aplicación usamos ColdFusion para conectarnos vía remoting. Esta todo escrito en ActionScript 2.0, y todo el código es externo, no hay ni una sola linea de código en la fla :)

El código también esta bien comentado ( lo único malo es que esta en ingles ) y también esta publicada la documentación de todas las clases. Otra cosa que pueden encontrar en el código son algunos componentes propios y la utilización del cell render en la datagrid. Bueno eso es todo espero que sirva como ejemplo.

Mirar el ejemplo online
Bajarse el código
Mirar la documentación

Post relacionados
Flash Remoting V2 + Trio Motor V2

July 20, 2005

Remoting tutorial - consumiendo web services con AMFPHP

klr20mg a sacado un interesante tutorial en el que explica como conectarse por medio de AMFPHP a los Web Services de MXNA

Articulos relacionados
Remoting tutorial
Autentificacion de usuarios con flashremoting

May 25, 2005

Conferencias en Cristalab

Freddie y compañia van a ofrecer una serie de conferencias a través de Breeze. La iniciativa me parece muy buena, tratando de evangeliazar acerca de las tendencias en Macromedia Flash. Sin duda estaré ahi, me podran encontrar con el nick de tangamampilia, pero seguramente Freddie me estará llamando Daniel del Rancho XD.
Esto es porque en la conferencia de prueba anoche, donde estabamos unas 6 personas, le comente que estaba en un rancho, que es como una especie de finca familiar. El caso es que habia otro Daniel (si, si...ya se....tira una piedra al azar, y seguramente le darás a un Daniel), y como no le gustaba pronunciar mi nick, pues me apodó Daniel del Rancho.

En fin...mas info de las conferencias aqui.


May 03, 2005

Autentificación de usuarios con FlashRemoting y setCredentials

A lo mejor algunas personas han escuchado hablar acerca de un método en Flash Remoting llamado setCredentials, y si no, pues vamos a explicarlo un poco. Antes les recomiendo leer este tutorial si no conoce mucho acerca de Remoting.
Flash Remoting para cuestiones de seguridad maneja un sistema interno basado en sesiones. Generalmente cuando nosotros desarrollamos un sitio seguro, requerimos ir pasando el identificador de sesión por cada petición a un archivo que requiera autentificacion. A veces usamos cookies, a veces usamos variables $_GET y el lenguaje del server side generalmente hace el resto automaticamente. El problema de las cookies es que en ocasiones puede que estén deshabilitadas en el navegador. En el caso de las variables $_GET puede llegar a ser tedioso tener que concatenar el identificador con los links en nuestra aplicación. De igual manera, en Flash, cuando hacemos peticiones vía LoadVars o XML, tenemos que elegir alguna de las dos opciones (o las dos) para hacer segura nuestra aplicación. En Flash Remoting, tenemos la ventaja de que existe un sistema nativo tremendamente fácil de utilizar e implementar (y curiosamente por mas fácil que este, hay muy poca documentación acerca de ello). Esto es mediante los setCredentials. La idea es la siguiente : creamos nuestro servicio en Flash, validamos un usuario mediante setCredentials y cada vez que queramos invocar un método que requiera autentificación de nuestra clase, se enviara automaticamente el identificador de sesión (sin que nosotros tengamos que preocuparnos por conocer tal numero). Entonces Flash Remoting nos devolverá o un ResultEvent o un FaultEvent dependiendo si la validación fue correcta o no. Previamente nosotros deberemos definir un servicio llamado _authentificate (en amfphp) que se invocara automaticamente cada vez llamemos al setCredentials. Este método deberá devolver "admin" en caso de que la validación sea correcta. Aquí, extendiendonos a un ejemplo mas real, podemos hacer una conexión a una base de datos donde tengamos registrados a nuestros usuarios. Veamos el siguiente código :

<?PHP

class SecuredConn {

function SecuredConn () {
$this->methodTable = array (
"welcome" => array(
"description" => "validate function",
"access" => "remote",
"roles" => "admin",
"arguments" => array()
)
);
}

function _authenticate($user, $password) {
if ($user == "daniel" && $password == "asfusion") {
return "admin";
}
else {
return false;
}
}
function welcome () {
return "bienvenido!!!!"
}
}
?>


También es importante notar, que dentro de la tabla de métodos, específicamente en el array welcome, hay una propiedad llamada roles, y seteandola como admin provoca que se requiera previamente validar al usuario mediante setCredentials.

En flash tenemos lo siguiente :

import mx.remoting.Service;
import mx.services.Log;
import mx.rpc.RelayResponder;
import mx.rpc.FaultEvent;
import mx.rpc.ResultEvent;
import mx.remoting.PendingCall;

var sSecured:Service = new Service ("gateway.php", null,"SecuredConn",null,null);
sSecured.connection.setCredentials ("daniel", "asfusion");

function welcomeResult (rs:ResultEvent) {
trace (rs.result);
}

function welcomeFault (fl:FaultEvent) {
trace("Su usuario no esta validado");
trace("Hubo un problema: "+fl.fault.faultstring);
trace("El código del error es: "+fl.fault.faultcode);
trace("Detalles: "+fl.fault.detail);
}

var pcWelcome:PendingCall = sSecured.welcome ();
pcWelcome.responder = new RelayResponder (this, "welcomeResult", "welcomeFault");


En este caso, veremos un mensaje en la ventana del output inidicandonos que el servicio fue llamado correctamente. Si comentamos la linea de los setCredentials, veremos que el servicio no fue invocado correctamente y nos devolverá un error indicandonos que no existe una variable $_SESSION (que es la que administra las sesiones en php). La ventaja de utilizar setCredentials es que si ademas de querer restringir ciertos métodos, es una manera fácil de hacerlo, ya que nosotros no tenemos que andar validando a cada rato.

Una recomendación muy importante, es que cada vez que queramos usar un servicio diferente (ojo: hablo de servicios, no de métodos), habrá que invocar nuevamente el setCredentials. O sea... estoy usando el servicio Noticias, con x numero de métodos. Me logueo con setCredentials y listo, no importa el numero de métodos que invoque, con el primer setCredentials me va a validar el usuario. Posteriormente quiero utilizar el servicio Estadísticas, entonces tengo que volver a registrarme con setCredentials. Un tip interesante es que para no tener que volver a escribir a cada rato el método _authentificate en sus servicios, les recomiendo que utilicen herencias de php. Por ejemplo, nuestro servicio anterior será la superclase de este servicio :

include_once("SecuredConn.php");

class News extends SecuredConn {

function News {
$this->methodTable = array (
"getNews" => array (
"description" => "Devuelve el listado de noticias",
"access" => "remote",
"roles" => "admin",
"arguments" => array ()
)
);
}

function getNews () {
return "AsFusion es un blog mas en la blogosfera que intenta sobrevivir en este mundo cruel";
}
}


La ventaja de este método, es que si por alguna razón mejoramos nuestro sistema de validación de usuarios (o bien, conectamos con una base de datos), nada mas habría que cambiar el método _authentificate en SecuredConn. Es importante señalar que esto nos ahorra mucho trabajo si estamos trabajando como varios servicios que requieran validación dentro de una aplicación.

Ademas, es posible que nosotros necesitemos dentro de nuestro método _authentificate agregar mas de dos argumentos, que es la cantidad limite que acepta, pongas los que les pongas al método _authentificate, ya que los componentes de Remoting de Flash únicamente envía dos argumentos, . Por ahí encontré en los foros de www.sephiroth.com un tip interesante : Utilizar el argumento de password como si fueran dos. Podemos separar ambos argumentos utilizando un caracter como #. A que me refiero:

sSecured.connection.setCredentials ("daniel", "asfusion#true");

En nuestro método del servicio únicamente lo que hacemos es "rebanar" el string utilizando split() por ejemplo. Otra manera, es pasandole un array (el cual me parece mas seguro) dentro de password o username.

Ya por ultimo, para desloguearse pueden hacer que se envíen los setCredentials en blanco, o utilizar el método logout que previamente han de definir en su servicio:

function logout () {
Authenticate::logout();
}


Ojalá les ayude este pequeño tutorial. Saludos!

January 05, 2005

AmfPhp casi listo al fin!

Acabo de entrar a flash-db y lo primero que lei fue esto:

The AMFPHP project 1.0 release is very near, developpers are working hard on this. You're encourage to help with this open source pryect posting on the wiki. Also you can join the mailing list in Sourceforge.net


Viendo esto me fui a la pagina del proyecto amfphp y después de 1 año y 4 meses publican una nueva nota en su sección de noticias. Sinceramente esto me pone muy contento, dado que desarrollar aplicaciones mediante remoting nos facilita la vida... en verdad, cualquier persona que lea y desee enfocarse a la creación de aplicaciones dinámicas con flash no puede dejar de conocer las bondades de AmfPhp (o similares). Como comentario aparte, creo que si bien FlashComm y FlashRemoting son tecnologías diferentes (y son las dos mas "novedosas" integraciones de flash y server side), sin duda esta última tiene mas posibilidades de ser aplicada en la vida diaria aunque haya sido un poco opacada por la primera.

Mas info aquí

Esto dará mucho de que hablar en varios blogs y comunidades.

November 04, 2004

Tutorial

Para comenzar, veamos que es exactamente Flash Remoting:

Flash Remoting es una tecnología que te permite hacer llamadas o pedidos a lenguajes de backend... como PHP, .NET o ColdFusion, pero sin tener conocimiento de ellos. La manera en que se puede trabajar con estas llamadas es un poco similar a la integración de Flash con los Web Services, solo que es mucho mejor, ya que toda la información se manda en formato binario y serializada. Estas llamadas se les denomina Remote Procedure Calls (RPC) y la transferencia de datos es mediante objetos que tanto el lenguaje de servidor como flash comparten. Como bien dijimos, la información se manda en formato binario mediante AMF (Action Message Format) el cual es mas rápido de cargar que informacion en formato XML nativo o por medio de cadenas URL, Incluso es mas rapido que con los Web Services. Nosotros para este tutorial utilizaremos la versión open source AMFPHP el cual funciona con el lenguaje PHP. Porque? porque es gratuito :) . Como apunte hay que recordar, como bien comentamos, hay Flash Remoting para .NET, Coldfusion, ademas de Java, los cuales fueron desarrollados por Macromedia y sus licencias son algo costosas. Otra opción gratuita son las librerías para Perl de Flash Remoting que pueden encontrar aquí.

Seguir leyendo.....

June 11, 2004

Flash Remoting V2 + Trio Motor V2

Como algunos ya sabrán Macromedia a sacado la nueva versión de Flash Remoting (v2), y si bien a cambiado un poco la sintaxis, el nuevo API es mucho mejor. Encontrarán por ejemplo que varias de las funciones del viejo remoting están fuera de uso ( deprecated ) y es por que un nuevo grupo de clases a tomado su lugar. Ahora nos dan un API más flexible y más cómodo para trabajar. Pero lo mejor de todo es que han mejorado notoriamente la documentación.

Y junto con estos componentes nuevos, también salió un articulo en Devnet (inglés) acerca de la nueva versión de Trio Motor en la que estamos trabajando. Este artículo escrito por mí en conjunto con Mike Kollen es el primero de una serie de tres y se base en el pequeño componente que se encuentra justo antes de entrar a la aplicación principal. En este artículo explicamos algunas de las clases de remoting como Service, PendingCall, Recordset, DataGlue, etc. Pero no cubrimos la parte del componente connector. Pero si también están interesados en ver un ejemplo del component connector, no se preocupen ya que he desarrollado una versión que lo utiliza, pero que al final no incluimos en el artículo. Así que el que guste le puede echar un vistazo. Lo único que tienen que asegurarse es que la GatewayUrl sea la misma que la que tienen configurada en su server. Ahora esta puesta como localhost, pero la pueden cambiar manualmente desde los parámetros del componente.

Muy pronto van a salir los dos artículos que siguen donde desarrollaremos mas la aplicación principal y nos meteremos mas de lleno la programación orientada a Objetos así que estén atentos.

Si surgen algunas dudas no duden en ponerlas en los comentarios.

Flash Remoting (v2)
Articulo en Devnet
Ejemplo del componente connector