WEB-d Développement Web
Posté le lundi 23 janvier 2012
Partager
Labels : PHP
Le fonctionnement des sessions peut être contrôlé à l'aide des paramètres session.* dans php.ini. La liste complète est disponible sur le site PHP.
Le premier paramètre qui nous intéresse est session.save_path qui détermine dans quel répertoire les fichiers de session doivent être sauvés. Il n'est pas toujours configuré par défaut, et il faudra donc manuellement éditer /etc/php5/apache2/php.ini pour indiquer session.save_path /tmp par exemple.
Certains des paramètres de configuration, mais pas tous, peuvent être modifiés au moyen d'une fonction spécifique (comme session_save_path($path) par exemple). Pour plus d'uniformité, je préfère ne pas utiliser ces fonctions et toujours utiliser ini_set('nom_du_paramètre', valeur).
Cookies de session
Si un même serveur héberge plusieurs applications différentes (http://serveur/app1/ et http://serveur/app2/ par exemple), on souhaite généralement que l'utilisateur reçoive un numéro de session différent pour chaque application, afin de ne pas mélanger les données dans la variable $_SESSION. C'est possible en utilisant ini_set('session.cookie_path', '/app1') qui limite la portée du cookie de session aux pages situées dans http://serveur/app1.
Si l'application possède un seul point d'entrée (http://server/app1/index.php?page=abc), grâce à de l'URL rewriting par exemple, on peut même utiliser dirname($_SERVER['PHP_SELF']) dans index.php. Une configuration complète ressemblera donc à ceci:
ini_set('session.use_cookies', true);
ini_set('session.use_only_cookies', true);
ini_set('session.cookie_lifetime', 5 * 60); // en secondes
ini_set('session.cookie_path', dirname($_SERVER['PHP_SELF']));
ini_set('session.cookie_domain', "");
ini_set('session.cookie_httponly', true); // PHP 5.2.0. minimum
ini_set('session.use_trans_sid', false);
session_start();
Attention cependant que le cookie de session n'est envoyé qu'une seule fois, lors de la création de la session. La durée de session configurée avec session.cookie_lifetime (5 min dans cet exemple) est donc une durée absolue, depuis la création de la session, et ne correspond PAS à 5 min depuis la dernière page vue. Pour modifier ce comportement, il faut envoyer manuellement le cookie au navigateur à chaque page vue, par exemple en utilisant la fonction suivante après session_start():
setcookie(
session_name(),
session_id(),
time() + ini_get('session.cookie_lifetime'),
ini_get('session.cookie_path'),
ini_get('session.cookie_domain'),
ini_get('session.cookie_secure'),
ini_get('session.cookie_httponly'));
Le Garbage Collector
Le Garbage Collector des sessions est chargé de supprimer les anciens fichiers de session qui ne sont plus utilisés. Par défaut, un fichier de session est supprimé 24h (1440 min) après sa création. Ce délais peut être changé en modifiant session.gc_maxlifetime (en minutes) dans php.ini.
Tout comme pour les cookies, ce délais démarre au moment de la création de la session. Pour modifier ce comportement, il faut créer soi-même un nouveau SessionHandler (voir session_set_save_handler()). Cependant, il vaut généralement mieux conserver le comportement par défaut, car il est recommandé de fixer une durée absolue maximale aux sessions, afin qu'un hacker qui aurait réussi un vol de session ne puisse garder un accès permanent à l'application.
Afin de ne pas rallentir l'affichage des pages, le Garbage Collector ne s'exécute pas à chaque page request, mais selon une probabilité calculée grâce aux options session.gc_probability / session.gc_divisor.
Posté le mardi 17 janvier 2012
Partager
Labels : PHP, Linux, Ubuntu
Suhosin est une extension de PHP qui permet de protéger un serveur contre une série de failles et d'attaques. Il ne protège naturellement pas contre toutes les attaques, et le développeur web devra donc toujours veiller à créer une application sécurisée, mais suhosin permet:
- de se protéger contre certaines failles du coeur PHP (comme par exemple la vulnérabilité "hash collision");
- d'éviter certaines fautes d’inattention du programmeur;
- de limiter les dégâts si une application web est compromise.

L'installation sur Ubuntu est comme toujours extrêmement simple:
apt-get install php5-suhosin
Le fichier de configuration de suhosin se trouve dans /etc/php5/apache2/conf.d/suhosin.ini, et la liste complète des options est clairement expliquée sur le site du projet Suhosin.
Une des options par défaut (suhosin.get.max_name_length=64) limite la longueur du nom des paramètres GET passés au script. Il est très facile de tester ce paramètre avec le code suivant:
<?php
var_dump($_GET);
?>
<a href="suhosin_test.php?abcd=1&azertyuiopqsdfghjklmwxcvbnazertyazertyuiopqsdfghjklmwxcvbnazertyazer=2">
Test...
</a>
Comme on peut le voir sur le screenshot ci-dessous, lorsqu'on utilise ce lien le deuxième paramètre (azert...) n'est pas transmis au script.

D'autres options intéressantes sont malheureusement désactivées par défaut, et il faudra donc les configurer manuellement:
- suhosin.executor.include.max_traversal=5
- suhosin.executor.disable_eval=On
- suhosin.executor.disable_emodifier=On
- suhosin.memory_limit=20M
Par défaut les alertes générées par Suhosin sont enregistrées dans /var/log/syslog. Ce n'est pas très pratique et je préfère donc utiliser un fichier séparé. Pour ce faire il suffit de créer un fichier /etc/rsyslog.d/30-suhosin.conf contenant les lignes suivantes:
:programname,contains,"suhosin" /var/log/suhosin.log
& ~
Puis de redémarrer rsyslog:
sudo restart rsyslog
Les alertes Suhosin seront désormais enregistrées dans /var/log/suhosin.log. Ce fichier est important car Suhosin pourrait malheureusement aussi empêcher certains scripts PHP de fonctionner correctement, mais c'est la contrepartie d'une plus grande sécurité...
Posté le samedi 24 décembre 2011
Partager
Labels : Javascript, Mootools
Une propriétés très puissante de Javascript, lorsqu'on sait l'utiliser, est les support des closures. Une closure est une variable qui contient la définition d'une fonction, plus la liste des variables à laquelle cette fonction peut accéder. C'est un concept de programmation proche, mais différent, des "anonymous functions" aussi appelées "lambda-functions".
Dans l'exemple ci-dessous, la closure "f" a accès aux variables globales "a" et "b":
<script type="text/javascript">
var a = "Hello";
var b = "World!";
var f = function() {
alert(a + " " + b);
}
f(); // Affiche "Hello World!"
</script>
Il faut cependant bien garder en mémoire que ce qui est sauvé dans la closure est la liste des variables, pas leur valeur. La valeur de la variable est calculée au moment de l'appel de la fonction. L'exemple suivant, par exemple, affiche "World!":
<script type="text/javascript">
var a = "Hello";
var f1 = function() {
alert(a);
}
a = "World!";
f1(); // Affiche "World!"
</script>
Cette particularité peut avoir des effets surprenants, surtout à l'intérieur d'une boucle:
<script type="text/javascript">
var my_functions = new Array();;
for (var i=0; i<3; i++) {
my_functions[i] = function() {
alert(i);
}
}
my_functions[0]();
my_functions[1]();
my_functions[2]();
</script>
L'exemple ci-dessus n'affiche PAS "1", "2", "3" comme on pourrait s'y attendre, mais bien "3", "3, "3". Comme la valeur de "i" est calculée au moment où on appelle la fonction, et comme cet appel a lieu après la fin de la boucle "for", la valeur de "i" est donc "3".
Heureusement, il existe quand même des techniques pour obtenir l'effet désiré. Dans le cas du framework mootoos, il s'agit de la fonction "pass(variable)":
<script type="text/javascript" src="mootools-core-1.3.2-full-compat-yc">
</script>
<script type="text/javascript">
var my_other_functions = new Array();
for (var i=0; i<3; i++) {
my_other_functions[i] = function() {
alert(arguments[0]); // la VALEUR de i est stockée dans arguments[0]
}.pass(i);
}
my_other_functions[0](); // Affiche "0"
my_other_functions[1](); // Affiche "1"
my_other_functions[2](); // Affiche "2"
</script>
Au moment où on utilise fonction.pass(variable), la VALEUR de cette variable est stockée dans arguments[0], et peut donc être utilisée. L'exemple ci-dessous affiche donc "1", "2" et "3".
La documentation complète de la fonction bind peut naturellement être trouvée sur le site de Mootools.
Posté le dimanche 11 décembre 2011
Partager
Labels : Javascript
La plupart des navigateurs modernes permettent maintenant d'obtenir facilement les coordonnées géographique de l'utilisateur. Il suffit pour cela d'utiliser le code javascript suivant :
navigator.geolocation.getCurrentPosition(showPosition, showError);
function showPosition(position) {
alert("Votre position: " + position.coords.latitude + " " + position.coords.longitude);
}
function showError() {
alert("Impossible d'obtenir votre position!");
}
Si l'utilisateur utilise un smartphone pour visiter votre site, le navigateur pourra, par exemple, utiliser le GPS du smartphone pour fournir les coordonnées. Cependant, les navigateurs 'de bureau' fournissent également de très bons résultats, en utilisant simplement l'adresse IP de la connexion internet.
Posté le vendredi 9 décembre 2011
Partager
Labels : PHP
Spreadsheet_Excel_Writer est un package PEAR qui permet, comme son nom l'indique, de créer des feuilles de calcul Excel. Pour l'installer, rien de plus simple :
sudo pear install -f Spreadsheet_Excel_Writer
L'utilisation est également simple, avec une particularité cependant. Les feuilles excel créées avec Spreadsheet_Excel_Writer sont encodées au format ISO-8859-1, alors que PHP utilise un encodage UTF-8. Pour que les caractères accentués s'affichent correctement, il faut donc utiliser la fonction utf8_decode($valeur) au moment d'écrire une valeur dans une cellule, comme le montre l'exemple complet ci-dessous :
<?php
include 'Spreadsheet/Excel/Writer.php';
$data = array(
array('', 'Math', 'Geo', 'Science'),
array('John', 24, 54, 38),
array('Marc', 67, 22, 57),
array('Tim', 69, 32, 58),
array('Tom', 81, 78, 68)
);
// Créer le fichier
$excel = new Spreadsheet_Excel_Writer();
// Ajouter une feuille de calcul
$sheet = $excel->addWorksheet('Feuille 1');
// Ajouter les données
foreach ($data as $line => $row) {
foreach ($row as $col => $value) {
// write(numéro de ligne, numéro de colonne, valeur)
$sheet->write($line, $col, utf8_decode($value));
}
}
// On l'enverra directement au navigateur
// (sans l'écrire sur le disque du serveur)
$excel->send('résultats.xls');
// Ne pas oublier de fermer le fichier
// Ce n'est que maintenant qu'il est envoyé au navigateur
if ($excel->close() !== true) {
echo 'ERREUR!';
}
?>
La documentation complète se trouve sur le site du projet PEAR.