Communiquer avec votre site Web
Table des matières
1) Introduction
2) Pré-requis
3) Préparation
4) Sécurisation de l'accès au script PHP
5) Requête simple (sans retour de données)
6) Requête avec retour (recevoir une réponse)
7) Un exemple concret : lecture d'un fichier XML de configuration
8) Conclusion
1) Introduction
Suite à une idée originale que Kozengod m'a apprise, je veux la partager avec le C# :)
Le but c'est de communiquer avec votre site Web par intermédiaire d'une page PHP contenant un script qui réagira en fonction de ce que votre programme envoi. L'accès à votre script PHP se fera en utilisant les variables super globales GET que vous traiterez en PHP.
Avec ce système vous pouvez par exemple utiliser votre base de donnée de votre hébergeur SANS librairie externe et SANS se soucier de son accès par le port 3306 vu que c'est votre site Web qui s'occupera de la requête.
Vous pourrez aussi recevoir des données : par exemple la liste des membres contenu dans votre base de donnée, obtenir l'heure de votre serveur etc.
Puisque nous traitons deux langages, le C# pour votre application et PHP pour votre script côté serveur, je considère que vous maîtrisez totalement le PHP et je ne commenterais pas plus les extraits de code qu'ils le sont déjà.
Vous l'avez compris, les possibilités sont énormes. Dans ce tutoriel je vais vous montrer une possibilité d'échanger des données avec un système de requête et de réponse.
2) Pré-requis
Le système à la base est simple et ne nécessite pas énormément de connaissances si ce n'est qu'un minimum en C# et après tout va dépendre de votre script PHP. Mais le système que je vous propose vous aurez besoin des connaissances suivantes :
- PHP : Pour pouvoir élaborer notre script côté serveur
- La structure DateTime pour pouvoir créer notre fonction qui génère une clé codée
- Les classes WebRequest et WebResponse
- La classe StreamReader
- Lecture des fichiers XML (Tutoriel : [C#] XML du site DotNet France )
Maintenant que vous avez toutes les connaissances nécessaires, nous allons commencer notre développement :)
3) Préparation
Sachez d'abord que ce tutoriel sera spécialement testé sur une application console ! En tant que développeur, j'adore l'écran noir et les lignes blanches :p
Non c'est surtout pour faire plaisir à certaines personnes ;)
Pour commencer, nous allons créer une classe WebCom qu'on va implémenter petit à petit de nos fonctions.
J'ai choisi de la faire static car elle n'aurait aucun intérêt à être utilisé en tant qu'instance.
Créez votre fichier WebCom.cs et commencez par le remplir avec la classe WebCom avec la fonction MD5.
(*** les usings ***)
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
(...)
public class WebCom
{
#region Attributs
/// <summary>
/// Mot de passe propore au développeur permettant de créer la clé.
/// </summary>
private static string _DevPassword = "RaphyTheGeek";
#endregion
#region Propriétés
#endregion
#region Méthodes privées
/// <summary>
/// Crée le hash MD5 de la valeur spécifiée
/// </summary>
/// <param name="value">Valeur à hacher.</param>
/// <returns>Une chaîne contenant le hash MD5 de la valeur spécifiée.</returns>
private static string MD5(string value)
{
System.Security.Cryptography.MD5CryptoServiceProvider cryptor = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] hash_bytes = System.Text.Encoding.UTF8.GetBytes(value);
hash_bytes = cryptor.ComputeHash(hash_bytes);
string buffer = string.Empty;
foreach (byte by in hash_bytes)
buffer += by.ToString("x2");
return buffer;
}
#endregion
#region Méthodes publiques
#endregion
}
En ce qui concerne le script PHP il va se composer en deux (ou plusieurs pages).
Une page WebCom.php qui va contenir le script permettant de vérifier la clé reçue et puis autant de pages que vous désirez où vous inclurerez dans chacun webcom.php. En ce qui nous concerne, dans ce tutoriel je ne vais créer qu'une seule : webcomtest.php :
<?php
/**
* webcomtest.php
**/
// On inclut notre fichier de base
require_once("webcom.php");
?>
4) Sécurisation de l'accès au script PHP
Nous allons tout d'abord commencer par sécuriser notre script PHP.
Pour cela nous allons élaborer un système de clé qui change toutes les 5 minutes.
La procédure est simple. Nous avons un mot de passe que nous définissons dans le code, puis prendre la date et l'heure actuelle au fuseau horaire UTC que nous allons convertir en un timestamp. Sur ce timestamp nous allons faire en sorte qu'il soit toujours égal à une heure multiple de 5 à la minute inférieure.
Pour obtenir la clé nous allons simplement faire un hash md5 du timestamp concaténé du mot de passe.
Dans la page webcom.php vous ajoutez :
<?php
// Mot de passe
$dev_password = "RaphyTheGeek";
// Fonction qui crée notre clé
function MakeKey($modif = 0)
{
global $dev_password;
$time = time();
$omin = date("i", $time) + $modif;
$min = ($omin % 5 != 0) ? $omin - ($omin % 5 ) : $omin;
$timestamp = mktime(date("H", $time), $min, 0, date("m", $time), date("d", $time), date("y", $time));
return md5($timestamp.$dev_password);
}
?>
Maintenant il nous reste à faire la même chose en C#, on va ajouter une fonction à notre classe :
/// <summary>
/// Crée la clé de sécurité.
/// </summary>
/// <returns>Retourne la chaîne contenant la clé de sécurité.</returns>
private static string MakeKey()
{
// Parsing de la date actuelle en UTC avec le décalage de 5 minutes.
DateTime utcdate = DateTime.UtcNow;
int int_min = (utcdate.Minute % 5 != 0) ? utcdate.Minute - (utcdate.Minute % 5) : utcdate.Minute;
string min = int_min.ToString().Length == 1 ? "0" + int_min : int_min.ToString();
DateTime date = DateTime.Parse(utcdate.Day + "/" + utcdate.Month + "/" + utcdate.Year + " " + utcdate.Hour + ":" + min + ":00");
// Calcul du timestamp de la date parsé.
long timestamp = date.Ticks - DateTime.Parse("01/01/1970 00:00:00").Ticks;
timestamp /= 10000000;
// Retour de la clé.
return MD5(timestamp.ToString() + _DevPassword);
}
Nous allons tester si les méthodes fonctionnent correctement et qu'elles sont identiques.
N'oubliez pas pendant la phase de test de mettre votre méthode MakeKey en public ;)
En PHP
echo MakeKey();
et en C# dans un programme console :
using System;
using System.Collections.Generic;
namespace TutoWebCom
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(WebCom.MakeKey());
}
}
}
Si vous obtenez la même chose c'est niquel, sinon veuillez demander de l'aide dans la section adéquate :)
Puisque tout fonctionne, il faut maintenant bloquer le script PHP si quelqu'un n'a pas la bonne clé ou qui accède à cette page par "inadvertance" ;)
Pour cela on va juste faire des conditions et un peu de méthode :p
// On vérifie que la clé est correcte pour continuer.
$authorized = false;
if(array_key_exists("key", $_GET))
{
if($_GET["key"] == MakeKey())
$authorized = true;
if($_GET["key"] == MakeKey(-5))
$authorized = true;
if($_GET["key"] == MakeKey(5))
$authorized = true;
}
if(!$authorized)
exit();
Donc vous devez avoir actuellement ce code pour votre fichier webcom.php
Cliquez pour révéler
Cliquez pour masquer
<?php
/**
* webcom.php
**/
// Mot de passe
$dev_password = "RaphyTheGeek";
// Fonction qui crée notre clé
function MakeKey($modif = 0)
{
global $dev_password;
$time = time();
$omin = date("i", $time) + $modif;
$min = ($omin % 5 != 0) ? $omin - ($omin % 5 ) : $omin;
$timestamp = mktime(date("H", $time), $min, 0, date("m", $time), date("d", $time), date("y", $time));
return md5($timestamp.$dev_password);
}
// On vérifie que la clé est correcte pour continuer.
$authorized = false;
if(array_key_exists("key", $_GET))
{
if($_GET["key"] == MakeKey())
$authorized = true;
if($_GET["key"] == MakeKey(-5))
$authorized = true;
if($_GET["key"] == MakeKey(5))
$authorized = true;
}
if(!$authorized)
exit();
?>
5) Requête simple
Maintenant que nous avons nos outils pour s'identifier à notre script eh bien on va continuer notre classe en C# :)
Nous allons ajouter une nouvelle méthode public et static appelé "Request" qui va avoir en arguments l'adresse de la page contenant le script et puis tous vos paramètres (les différentes valeurs dans $_GET) qui est de type Dictionnary<string, string>.
Dans cette méthode nous allons premièrement créer notre adresse complète à partir de l'adresse de page fournie et des arguments.
Puis en utilisant la classe WebRequest, on va demander d’accéder au lien précédemment crée.
Et voilà la requête a été effectuée.
Voyons voir maintenant ce que ça donne en code :p
Notre fonction ressemble à ça :
public static void Request(string url, Dictionary<string, string> args)
{
}
Pour pouvoir créer notre lien complet on va tout simplement concaténer notre url avec les clés associées aux valeurs du dictionnaire args.
En clair ça donne ça :
// Création de l'url avec les arguments
string fullURL = url + "?key=" + MakeKey(); // on oublie pas d'ajouter notre clé ;)
foreach (KeyValuePair<string, string> kvp in args)
fullURL += "&" + kvp.Key + "=" + kvp.Value;
Une fois qu'on a notre adresse complète, on crée la requête avec WebRequest :
// Requête.
WebRequest request = WebRequest.Create(fullURL);
request.GetResponse();
Dans votre fichier webcomtest.php, on fera en sorte de créer un fichier message.txt et qui va contenir le message envoyé par votre application
<?php
/**
* webcomtest.php
**/
require_once("webcom.php");
if(!file_exists("message.txt"))
{
$create_file = fopen('message.txt', 'a+');
fclose($create_file);
}
$file = fopen('message.txt', 'r+');
fputs($file, $_GET["message"]);
fclose($file);
echo 'Message : '.$_GET["message"]."\r\n";
?>
De retour dans notre application console, on va effectuer notre première requête ! Tenez vous prêt ça va être.. simple !
// On crée notre dictionnaire contenant les variables et leurs valeurs.
Dictionary<string, string> variables = new Dictionary<string, string>();
// On demande le message à écrire
Console.Write("Entre votre message : ");
string message = Console.ReadLine();
// On ajoute une nouvelle entrée.
// $_GET["message] = $message
// ?key=(...)&message=(valeur de "message")
variables.Add("message", message);
// Exécution de la requête
WebCom.Request("http://localhost/webcomtest.php", variables);
Console.ReadLine();
Vérifiez votre fichier message.txt et admirez la merveille :)
6) Requête avec retour
Pour créer une requête avec retour on va simplement mettre à jour notre méthode Request actuelle.
Déjà on va lui donner un type de retour qui sera un string.
On va changer un peu la réponse de WebRequest :
// Requête et réponse.
WebRequest request = WebRequest.Create(fullURL);
WebResponse response = request.GetResponse();
Puis on va juste lire le contenu du stream de la réponse ;)
/!\ ATTENTION A L'ENCODAGE ! /!\ Mettez l'encodage correct à vos fichiers !
StreamReader stream = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
return stream.ReadToEnd();
Voici la fonction Request entière et optimisée
Cliquez pour révéler
Cliquez pour masquer
public static string Request(string url, Dictionary<string, string> args)
{
// Création de l'url avec les arguments
string fullURL = url + "?key=" + MakeKey();
foreach (KeyValuePair<string, string> kvp in args)
fullURL += "&" + kvp.Key + "=" + kvp.Value;
StreamReader stream = null;
try
{
// Requête et réponse.
WebRequest request = WebRequest.Create(fullURL);
WebResponse response = request.GetResponse();
// Lecture des données.
stream = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
return stream.ReadToEnd();
}
catch
{
return null;
}
finally
{
if (stream != null)
stream.Close();
}
}
Faisons un petit test maintenant avec notre application console !
Console.WriteLine(WebCom.Request("http://localhost/webcomtest.php", variables));
Magique !
Pour ceux qui se sont perdus en route :
Cliquez pour révéler
Cliquez pour masquer
Vous devez avoir une classe WebCom qui ressemble à ceci :
Loading Image
A venir : lecture d'un fichier XML
Le tuto peut être considéré comme fini. Je vais essayer de vous montrer un exemple concret avec les fichiers XML dès que j'en aurais l'occasion.
8) Conclusion
Comme vous l'avez sans doute remarqué par vous même, les possibilités sont infinies !
A vous d'utiliser cette méthode à bon escient et correctement.
J’espère que ça vous a plu et grand merci à Kozengod :)