setCredentials con Base de Datos
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¡
Un error en el articulo anterior con el método log() de la clase Config.
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!
Uso de herencia en AMFPHP en 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!
Trio Motor un ejemplo de una aplicación hecha con Remoting
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
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
Conferencias en Cristalab
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.
Autentificación de usuarios con FlashRemoting y setCredentials
<?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!
AmfPhp casi listo al fin!
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.
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í.
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
