Cette classe permet de récupérer les données provenant d'une requête faite à partir du flash.
La requête est cryptée et envoyé au php (fichier data.php) qui la décrypte pour la traiter.
C'est juste un début, il n'y a pas de gestion des erreurs.
La classe intègre l'évènement "fin_requete" qui permet d'agit et récupérer les infos au moment que le résultat arrive et il est prêt.
=== config ==============================================================
La configuration de la base de données (serveur, user et pass) se fait sur mysql.php
Sur le fichier de classe on doit configurer le URL du fichier data.php
=========================================================================
Source / Exemple :
//======================================================
// utilisation de la classe MySqlConn
//======================================================
/// on definit l'instance de classe
var mysql:MySqlConn = new MySqlConn();
//// on applique une requete
mysql.query_exec("select nom, prenom from matable");
/// on gère l'évenement de fin requete
mysql.addEventListener("fin_requete", vasy);
///// on execute une fonction et on gère les valeurs obtenues
///// chaque ligne aura un array ligne[i] (de 1 à n_lignes)
///// chaque élément du tableau est un objet dont les propriétés
///// sont nommées comme les champs qui résultent de la requete
function vasy(e):void{
var n_lignes:int = e.target.n_lignes;
for (var i:int=1; i<=n_lignes;i++){
trace(e.target.ligne[i].nom);
trace(e.target.ligne[i].prenom);
}
}
//======================================================
// classe
//======================================================
package
{
/**
import flash.events.*;
import flash.net.*;
import flash.utils.getTimer;
import flash.display.*;
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@ CLASSE MySqlConn
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
public class MySqlConn extends Sprite
{
//////////////////////////////////////////////////////////////////////////////////////////
///// V A R I A B L E S
//////////////////////////////////////////////////////////////////////////////////////////
//============= criptage ===================================
private var chiave:String = "abcdyfx9ilk";
//============= URL ===================================
//private var base_url:String = "";
private var base_url:String = "
http://127.0.0.1/votresite/";
private var file_data :String = base_url+"data.php";
//============= autres ===================================
public var ligne:Array = new Array();
public var n_fields:int = -1;
public var n_lignes:int = -1;
//////////////////////////////////////////////////////////////////////////////////////////
///// M E T H O D E S
//////////////////////////////////////////////////////////////////////////////////////////
public function MySqlConn()
{
}
public function query(str:String):String {
var i:Number = 0;
var count:Number = str.length;
var final:String = "";
while (i<count){
var ch:String = str.substr(i,1);
var char:String = String( ch.charCodeAt(0) );
for (var j:int=1; j<=char.length; j++) {
var lettre:String = String(char.substr(j-1, 1));
if (lettre == "0") {
lettre = "10";
}
var nouvelle:String = chiave.substr(int(lettre),1);
final += nouvelle;
}
final += chiave.substr(0,1);
i++;
}
return final;
}
public function query_exec(req_str:String):void {
////// PARTE VARIABILI =========================
var variables:URLVariables = new URLVariables();
variables.alea = getTimer();
variables.rq = query(req_str);
//trace(variables.toString());
////// PARTE REQUEST =========================
var request:URLRequest = new URLRequest(file_data);
request.method = URLRequestMethod.POST;
request.data = variables; /// è qui che si lega a variables
////// PARTE LOADER =========================
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.VARIABLES;
loader.load(request);
loader.addEventListener("complete", vasy);
function vasy(e:Event):void{
var ind_i:int = 0;
var ind_j:int = 0;
n_fields = e.currentTarget.data.n_fields;
n_lignes = e.currentTarget.data.n_rows;
ligne.splice(0,ligne.length);
for (ind_i = 1; ind_i <= n_lignes; ind_i++) { /// lignes
var champs:Object = new Object();
for (ind_j = 1; ind_j <= n_fields; ind_j++) { /// champs
var nom_champs:String = e.currentTarget.data["field" + ind_j];
champs[nom_champs] = e.currentTarget.data[nom_champs + ind_i];
}
ligne[ind_i] = champs;
}
dispatchEvent(new Event("fin_requete"));
}
}
} /// Fin classe
} /// Fin package
Conclusion :
J'ai juste voulu vous donner une piste, mais bien sur c'est un début. Par exemple une variable insert_id pourrait envoyer l'id provenant par une requête INSERT (déjà fat sur le data.php mais pas encore au niveau du as).
13 avril 2011 à 14:28
il y a une chose sur laquelle je suis vraiment d'accord... le fait de dissocier la partie client de la partie serveur et de laisser au serveur gérer les données et au client les manipuler via du simple IHM.
En Flash il y a une technique pas trop utilisée qui fait plus ou moins ça, mais à l'inverse : le flash remoting.
Il part du principe que coté serveur chacun choisi si mettre du php, du .NET, du java....
Il utilise donc un format d'échange (AMF) qui permet au client flash de piloter des classes distantes et de récupérer les datas renvoyés par les méthodes de classe.
Donc en gros je pense qu'il soit déjà bien performant, pas besoin d'aller plus loin....
J'ai utilisé ce système et c'est très bien. Pour certains développements il est fort nécessaire d'utiliser une logique IHM séparé de l'"intelligence" du serveur.
Mais je reste de l'opinion, qu'il soit pas complètement absurde de faire du sql sur du flash, mais ça dépend strictement du contexte.
Je prends tes exemples...
1) un logiciel de facturation en flash : chaque client a (évidement) une base de données différente, donc le problème ne se pose pas. Chacun peut attaquer que soit même. On donne juste le droit au SELECT, UPDATE, INSERT, DELETE...
2) Un logiciel collaboratif : ça serait au minimum pas prudent d'utiliser un système comme ça. Ou sinon on utilise ça pour toute la partie SELECT, et pour le reste (UPDATE, DELETE... ) on utilise la logique standard.
3) un jeu dans lequel les gens peuvent y inscrire leur score, un formulaire d'inscription à une newsletter, un formulaire de vote : pareil que le point N° 2
Donc voilà je suis d'accord sur le principe que ma méthode est bien délicate, et pas trop structurée. Je dois avouer que tes arguments sont quand même bien solides...
merci
Emanuele
11 avril 2011 à 19:28
* Flash exécution côté client présentation (principe MVC)* PHP exécution côté serveur modèle / contrôleur
Pour faire simple, t'as pas trop le choix ... aucun framework ne permettrait d'embarquer la logique métier et le mapping côté client.
De plus, tu fais aujourd'hui du flash ... OK
Demain tu veux faire un petit soft en .NET en client lourd ... tu refais toutes les requêtes ?
La partie IHM (=côte client) est la partie la plus évolutive et la plus sujette aux évolutions techniques ... embarquer la logique métier ne servirais qu'à l'alourdir voire même t'obliger à la faire évoluer ou la ré-écrire en changeant de techno.
Maintenant côté code, rien ne t'empêche de faire la même chose que t'as fait style mysql.remplir(...); en version plus propre :
Ton service PHP retourne un array de valeurs, il est exposé style : http://domaine/services/MyService/GetItems.xml
(par exemple : le .xml indique qu'on attend du XML)
Ton SDK côté flash aurait un truc du style :
conn = SDK.Connect("http://domaine/");
Coté classes AS tu aurait une class de mapping :
class MyService {
... conn;
public MyService(conn) ...
ArrayList GetItems() {
return conn.Request("MyService", "GetItems");
}
}
Tu peux faire :
service = new MyService(conn);
ArrayList items = service.GetItems();
Ou bien tu te fais un helper pour reproduire ta fonction :
Helper.Assign(service.GetItems(), this);
C'est très schématique, mais cela te montre que plus tu as de niveaux d'abstractions et plus tu as moins à travailler.
Concernant l'attaque sur ton domaine : www.as-ql.org, tu dois t'assurer que l'attaque ne vient pas de l'intérieur.
Je te donne quelques exemples : tu fais un logiciel de facturation en flash, tu ne peux pas le proposer en SaaS (ou imagines sinon que les concurrents vont aller s'espionner entre eux).
Tu fais un logiciel collaboratif là encore tu peux pas, du moment où les utilisateurs n'ont pas tous les mêmes droits ou des droits restreints ta librairie n'est pas utilisable ...
Tu fais un jeu dans lequel les gens peuvent y inscrire leur score, tu fais un formulaire de d'inscription à une newsletter, un formulaire de vote ...etc...
Tu peux faire un très joli truc, fais les couches que j'ai décrit dans mon précédent message et puis rajoutes unes couche RAD comme tu l'as déjà fait pour ton framework ...
Bon courage pour la suite de tes dévs :)
11 avril 2011 à 17:55
Le problème de fond que tu évoques et que tu as très bien ciblé est que au niveau de l'utilisateur, lui il a "plus de droits qu'il ne devrait" avoir.
Maintenant si je vois tes solutions il n'y a rien qui permettrait (sauf si je me trompe bien sur) d'écrire en dur les requêtes sur les *.as et au même temps d'améliorer ce gros problème de sécurité.
Et si tu dois écrire les requêtes ailleurs, par exemple dans des classes php, et en utilisant une passerelle AMF, on perd completement le principe même de ce que je voulais faire.
Je suis en train d'écrire des classe as3 qui sont vraiment simples et au même temps super puissantes. Par exemple tu fais
mysql.remplir("select nom, prenom from table where id=1",this);
et as va chercher sur this les composants nom et prenom. Il vérifie s'il s'agit d'un TextField ou d'un textarea et il remplace les valeurs.
Je pense qu'il soit pas possible (en fin je l'avoue) de sécuriser ce genre de système pour un usage l'utilisateur. Mais si le swf est derrière un htaccess, ou bien l'utilisateur mysql peut faire juste des selects, ou bien on a un superutilisateur que lui seul connait le mot de passe d'accés, alors dans ces contextes, ce système est très utile.
Ok il est un peu rigide, mais souvent on s'y perd en pensant à la sécurité, et on perd completement de vue nos objectifs.
Concernant mon défis, le site www.as-ql.org et encore là et personne a pu l'attaquer. J'ai envoyé un lien à pas mal de monde dans mon entourage, et pour l'instant ça tient.
Mais si on réfléchi un peu : sur un site Internet fait en flash très rarement on fait des utilisateurs
11 avril 2011 à 12:36
J'ai bossé sur quelque chose de très similaire (publié sur flashkod : http://www.flashkod.com/codes/CLASSE-LIAISON-REQUETTAGE-AVEC-SERVEUR-MYSQL-DISTANT-XSQL_38305.aspx) mais avec la notion de sécurité en moins compliqué, mais avec les mêmes failles qu'a relevé Peg.
Je pense comprendre un peu vos deux problématiques, et peut-être qu'un peu de retour sur mon expérience va t'éclairer.
A première vue Peg à l'air de chercher la petite bête mais en réalité il a tout à fait raison, c'est juste qu'il ne l'exprime pas assez clairement :
Je voulais faire du SQL dans du flash, comme j'aurais très bien pu le faire en ajax / javascript. Le problème peut ne pas se poser à première vue car l'utilisateur exécutant le code est identifié, donc un guest ne peut pas nuire.
Le problème se pose à deux niveaux :
- l'utilisateur connecté peut lui avoir plus de droits qu'il ne devrait ... mais étant faignant de ce côté je m'en fout du moment où ça m'aide (j'estime qu'être faignant en informatique est une qualité au passage :)
- autre problème c'est la logique métier et la ré-utilisabilité et c'est là que le bat blesse :)
Etant faignant je ne voulais pas avoir à écrire le SQL à chaque fois, répéter des règles métier complexes, ou bien en changeant la structure repasser par des kilomètres de code.
Du coup quand tu deal avec des bases de données, la bonne pratique veut que tu en fasses des objets. Le choix de l'environnement où tu fais ton objet est important, on pourrait être tenté de le faire en flash (avec tous les problèmes que ça pose au niveau sécurité) ou bien le faire côté PHP, permettant ainsi de partager les ressources côté ajax, flash, ou bien un MVC classique avec des vues en HTML.
Donc pour répondre à ta source, tu as raison sur le fond, mais tu t'y prends de la mauvaise manière.
Ce que t'aurais dû chercher à faire :
Une partie API :
- c'est d'intégrer un ORM, avec un DBAL
- faire des helpers pour la sérialisation : XML, JSON, CSV ...
- un équivalent de ton data.php pour le routage des appels en mode REST, et utilisant les helpers pour exprimer les retours
- un mode session ou quelquechose d'équivalent permettant de sécuriser l'appel de certains services
Une partie SDK :
- des classes de base pour les autres languages
* Flash
* Javascript
- éventuellement si tu est motivé, à partir d'une classe PHP tu peux générer l'enveloppe AS ou JS te permettant de ne pas perdre du temps sur une seconde re-définition (cf PHP+Reflection).
Dans le principe ça serait un peu similaire à ça : http://www.phpcs.com/codes/AJAX-TOOLKIT-PARTAGE-CLASSES-ENTRE-PHP-JS_47075.aspx
------
Lorque t'enchaines sur la création d'un nouveau projet avec ton framework, tu fais côté PHP tes classes qui gèrent la base de données, et puis tu inclues dans ton flash les enablers AS qui leur correspondent.
Le tout sera : optimisé, sécurisé, simple, ré-utilisable, évolutif
Bon courage, si tu ponds un projet comme ça n'hésites pas à me prévenir :))
akh
8 avril 2011 à 09:41
D'ailleurs le cryptage là il sert pas à faire transiter les données, mais juste les commandes.
Et comme on l'a bien dit, on pourrait s'en passer à condition de garder la notion de clef (jeton) envoyé par le php.
Quand j'ai dit de crypter avec une notion supplémentaire (par exemple port client du navigateur) c'était juste pour éviter que si quelqu'un tombe sur cette clef il puisse attaquer le serveur.
Exemple : la clef est "abc". Le php remarque que le port client est 3456. Il va pa envoyer "abc", mais "a165jhdk45" qui est rien d'autre que la clef "abc" crypté avec 3456. En revanche quand il fait du décryptage, il va avant tout chercher le port client pour crypter la clef "abc" et avec ce qu'il obtient il va décrypter la requête.
Si quelqu'un se met à sniffer le réseau où le client flash est installé il va trouver la clef, mais il pourra pas s'en servir. Et même s'il sait que la clef est crypté avec le port client, il peut pas s'en servir parce qu'il connait pas la façon avec laquelle le serveur a crypté la clef.
Donc il reste juste le problème de la gestion des utilisateurs. Là pour l'instant on peut avoir un seul super administrateur. Et si on définit un utilisateur standard, dès qu'il peut écrire la moindre chose, du coup il peut tout casser.
C'est ça le vrai problème... une idée ?
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.