<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3073819899020661481</id><updated>2024-11-01T10:04:07.381+01:00</updated><category term="php"/><category term="sécurité"/><category term="cookies"/><category term="zend framework"/><category term="atom"/><category term="csrf"/><category term="ergonomie"/><category term="feed"/><category term="idees"/><category term="memcache"/><category term="presentation"/><category term="pubsubhubbub"/><category term="rss"/><category term="workqueue"/><title type='text'>BigOrNot [fr]</title><subtitle type='html'>Les aventures d&#39;un web incrémental, contées par un calibreur de bigorneaux.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bigornot-fr.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default'/><link rel='alternate' type='text/html' href='http://bigornot-fr.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Mat</name><uri>http://www.blogger.com/profile/15945738194810734875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3073819899020661481.post-7659511282348778815</id><published>2009-11-16T11:50:00.006+01:00</published><updated>2009-11-16T13:32:12.621+01:00</updated><title type='text'>Quelle librairie utilisez vous pour generer vos flux Atom et RSS ?</title><content type='html'>&lt;p&gt;Jusqu&#39;à présent, j&#39;utilisais &lt;a href=&quot;http://framework.zend.com/manual/fr/zend.feed.importing.html#zend.feed.importing.custom.importarray&quot;&gt;Zend_Feed&lt;/a&gt; pour générer mes flux RSS et Atom. Tout allait très bien jusqu&#39;à ce que je veuille publier un flux sur un hub &lt;a href=&quot;http://bigornot-fr.blogspot.com/2009/11/pubsubhubbub-et-generation-de-flux.html&quot;&gt;PubSubHubbub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pour rappel, voici quelle tête doit avoir un flux Atom pour cette utilisation :&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;
&amp;lt;feed xmlns=&quot;http://www.w3.org/2005/Atom&quot;&amp;gt;
...
&amp;lt;link rel=&quot;self&quot; href=&quot;http://example.com/mon-flux.rss&quot; /&amp;gt;
&amp;lt;link rel=&quot;hub&quot; href=&quot;http://pubsubhubbub.appspot.com&quot; /&amp;gt;
&amp;lt;link rel=&quot;hub&quot; href=&quot;http://superfeedr.com/hubbub&quot; /&amp;gt;
...
&amp;lt;/feed&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Comme vous pouvez le constater, il est nécessaire de définir un élément &lt;span style=&quot;font-weight:bold;&quot;&gt;&amp;lt;link&amp;gt;&lt;/span&gt; supplémentaire avec l&#39;attribut &lt;span style=&quot;font-weight:bold;&quot;&gt;rel=&quot;hub&quot;&lt;/span&gt; pour chaque hub que vous voulez utiliser.&lt;/p&gt;

&lt;p&gt;En RSS, c&#39;est le même principe en utilisant le namespace atom (cf le &lt;a href=&quot;http://code.google.com/p/pubsubhubbub/wiki/RssFeeds&quot;&gt;wiki pubsubhubbub&lt;/a&gt;) :&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;rss xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot;&amp;gt;
&amp;lt;channel&amp;gt;
&amp;lt;link&amp;gt;http://example.com/mon-flux.atom&amp;lt;/link&amp;gt;
&amp;lt;atom:link rel=&quot;hub&quot; href=&quot;http://pubsubhubbub.appspot.com&quot;/&amp;gt;
&amp;lt;atom:link rel=&quot;hub&quot; href=&quot;http://superfeedr.com/hubbub&quot;/&amp;gt;
...
&amp;lt;/channel&amp;gt;
&amp;lt;/rss&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Le problème, c&#39;est que je n&#39;ai trouvé aucune librairie de génération de flux me permettant de faire cela. J&#39;ai donc finalement utilisé la classe native php &lt;a href=&quot;http://php.net/manual/fr/class.domdocument.php&quot;&gt;DOMDocument&lt;/a&gt; pour générer mes flux Atom et RSS. Je trouve cela dommage... d&#39;où mon article.&lt;/p&gt;

&lt;p style=&quot;font-weight: bold&quot;&gt;Et vous, quelle librairie utilisez vous ? En connaissez vous une qui puisse gérer ce cas ?&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigornot-fr.blogspot.com/feeds/7659511282348778815/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3073819899020661481/7659511282348778815' title='6 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/7659511282348778815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/7659511282348778815'/><link rel='alternate' type='text/html' href='http://bigornot-fr.blogspot.com/2009/11/quelle-librairie-utilisez-vous-pour.html' title='Quelle librairie utilisez vous pour generer vos flux Atom et RSS ?'/><author><name>Mat</name><uri>http://www.blogger.com/profile/15945738194810734875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3073819899020661481.post-1038852463003308530</id><published>2009-11-12T21:46:00.017+01:00</published><updated>2010-02-11T01:48:48.489+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="atom"/><category scheme="http://www.blogger.com/atom/ns#" term="feed"/><category scheme="http://www.blogger.com/atom/ns#" term="pubsubhubbub"/><category scheme="http://www.blogger.com/atom/ns#" term="rss"/><title type='text'>Présentation de PubSubHubbub</title><content type='html'>&lt;p&gt;J&#39;ai récemment découvert &lt;a href=&quot;http://code.google.com/p/pubsubhubbub/&quot;&gt;PubSubHubbub&lt;/a&gt; : un protocole simple et redoutable permettant d&#39;apporter du temps réel à la publication de flux RSS / Atom.&lt;/p&gt;

&lt;a href=&quot;http://bradfitz.com/&quot;&gt;Brad Fitzpatrick&lt;/a&gt;, l&#39;un des concepteurs de ce protocole, propose une &lt;a href=&quot;http://oopsiedaisy.typepad.com/dollop_of_daisy/2009/09/pubsubhubhub-for-dummies-and-yes-by-dummies-i-mean-me.html&quot;&gt;description assez imagée&lt;/a&gt; du principe, dont voici l&#39;adaptation en français :
&lt;blockquote&gt;&lt;p&gt;Imaginez vos enfants à l&#39;arrière de la voiture en train de demander sans cesse &quot;Quand est-ce qu&#39;on arrive ? Quand est-ce qu&#39;on arrive ?&quot;. La ferme les enfants ! je vous dirais quand on y sera !&lt;/p&gt;

&lt;p&gt;Ce phénomène, on l&#39;appelle Hubbub en anglais (&lt;span style=&quot;font-family:Arial;&quot;&gt;a confused noise of many voices&lt;/span&gt;). Sauf que dans notre cas, les enfants, ce sont en fait des sites Web en train de se parler. La façon dont les sites se parlent de nos jours ressemble à ça : &quot;Du nouveau ? Non. Du nouveau ? Non. Du nouveau ? Non. Du nouveau ? Non&quot;.&lt;/p&gt;

&lt;p&gt;PubSubHubbub corrige ce problème : les sites se parlent uniquement lorsqu&#39;il y a du changement.&lt;/p&gt;
&lt;/blockquote&gt;
Dans ce système, on peut distinguer trois type d&#39;acteurs :
&lt;ul&gt;&lt;li&gt;Les &quot;&lt;span style=&quot;font-weight: bold;&quot;&gt;publishers&lt;/span&gt;&quot; : ils publient du contenu (sous forme de flux &lt;a href=&quot;http://fr.wikipedia.org/wiki/Atom&quot;&gt;Atom&lt;/a&gt; ou &lt;a href=&quot;http://fr.wikipedia.org/wiki/RSS_%28format%29&quot;&gt;RSS&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Les &quot;&lt;span style=&quot;font-weight: bold;&quot;&gt;subscriber&lt;/span&gt;&quot; : ils s&#39;abonnent à des flux et sont informés à chaque mise à jour (sous forme de &lt;a href=&quot;http://wiki.webhooks.org/&quot;&gt;web hooks&lt;/a&gt;)
&lt;/li&gt;&lt;li&gt;Les &quot;&lt;span style=&quot;font-weight: bold;&quot;&gt;hub&lt;/span&gt;&quot; : c&#39;est l&#39;intermédiaire, qui s&#39;occupe de transmettre aux subscriber les notifications de mise à jour des flux auxquels ils sont abonnés&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Comme je le disais en introduction, cela permet d&#39;ajouter une touche de temps réel à ce monde de flux ! Voyons voir maintenant comment cela fonctionne dans la vraie vie ;-)&lt;/p&gt;

&lt;p&gt;On va commencer par une bonne nouvelle : vous n&#39;êtes pas obligés d&#39;héberger votre propre Hub pour jouer avec PubSubHubbub. Voici une &lt;a href=&quot;http://code.google.com/p/pubsubhubbub/wiki/Hubs&quot;&gt;liste de hubs publiques&lt;/a&gt;. Les deux plus populaires sont :&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a name=&quot;Hub_implementations_and_hosted_services&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://pubsubhubbub.appspot.com/&quot; rel=&quot;nofollow&quot;&gt;http://pubsubhubbub.appspot.com&lt;/a&gt; : une démo de l&#39;implémentation de référence en Python hebergée sur &lt;a href=&quot;http://code.google.com/appengine/&quot;&gt;Google App Engine&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://superfeedr.com/hubbub&quot;&gt;http://superfeedr.com/hubbub&lt;/a&gt;
&lt;/li&gt;&lt;/ul&gt;
En tant que &lt;span style=&quot;font-weight: bold;&quot;&gt;publisher&lt;/span&gt;, c&#39;est extrêmement simple.
&lt;ol&gt;&lt;li&gt;Selectionnez un ou plusieurs hubs auxquels vous allez déléguer la distribution de votre flux.
Je vous conseille d&#39;en prendre plusieurs, en cas d&#39;indisponibilité de l&#39;un d&#39;entre eux.

&lt;/li&gt;&lt;li&gt;Indiquez dans votre flux RSS ou Atom l&#39;url de votre hub.

Si vous avez un flux RSS, modifiez le de cette façon pour ajouter le namespace atom et un element &amp;lt;atom:link&amp;gt; :
&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;rss xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot;&amp;gt;
&amp;lt;channel&amp;gt;
&amp;lt;atom:link rel=&quot;hub&quot; href=&quot;http://pubsubhubbub.appspot.com&quot;/&amp;gt;
...
&amp;lt;/channel&amp;gt;
&amp;lt;/rss&amp;gt;
&lt;/pre&gt;

Si vous avez un flux Atom, il suffit de rajouter un element link a votre feed :
&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;
&amp;lt;feed xmlns=&quot;http://www.w3.org/2005/Atom&quot;&amp;gt;
&amp;lt;link rel=&quot;hub&quot; href=&quot;http://myhub.example.com/endpoint&quot; /&amp;gt;
...
&amp;lt;/feed&amp;gt;
&lt;/pre&gt;

&lt;/li&gt;&lt;li&gt;A chaque modification de votre flux, informez votre hub avec la &lt;a href=&quot;http://code.google.com/p/pubsubhubbub/wiki/PublisherClients&quot;&gt;librairie PubSubHubbub de votre language préféré&lt;/a&gt;.  Voyons à quel point c&#39;est difficile en PHP :
&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;
$p = new Publisher(&#39;http://superfeedr.com/hubbub&#39;);
$p-&gt;publish_update(&#39;http://example.com/url-de-mon-flux.rss&#39;);
&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Pour la partie subscriber que je n&#39;ai pas encore abordé,  je vous invite à consulter &lt;a href=&quot;http://code.google.com/p/pubsubhubbub/source/browse/trunk/subscriber_clients/php/example.php&quot;&gt;un exemple d&#39;implémentation en PHP sur le repository de PubSubHubbub&lt;/a&gt;. Pour cette partie, méfiez vous car ce n&#39;est pas si simple qu&#39;il n&#39;y parait : touts souscription à un flux possède une date d&#39;expiration. Il faut relancer une requête de souscription avant expiration afin de renouveller son abonnement. Je vous invite à consulter les &lt;a href=&quot;http://pubsubhubbub.googlecode.com/svn/trunk/pubsubhubbub-core-0.2.html&quot;&gt;spécifications du protocole&lt;/a&gt; pour plus de détails.&lt;/p&gt;

&lt;p&gt;Prochainement (dans moins d&#39;un an cette fois-ci, promis !) j&#39;aborderais un problème que j&#39;ai rencontré avec PHP pour mettre ce système en place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edit (11/02/2009) :&lt;/strong&gt; Bonne nouvelle : Google Buzz, le nouveau service de Google, est un subscriber PubSubHubbub ! Si vos flux sont publi&amp;eacute;s sur un hub, leur contenu pourra donc apparaitre instantanément dans Google Buzz !&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigornot-fr.blogspot.com/feeds/1038852463003308530/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3073819899020661481/1038852463003308530' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/1038852463003308530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/1038852463003308530'/><link rel='alternate' type='text/html' href='http://bigornot-fr.blogspot.com/2009/11/pubsubhubbub-et-generation-de-flux.html' title='Présentation de PubSubHubbub'/><author><name>Mat</name><uri>http://www.blogger.com/profile/15945738194810734875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3073819899020661481.post-2919322773834557308</id><published>2008-11-09T11:05:00.011+01:00</published><updated>2008-11-11T23:38:30.671+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="workqueue"/><title type='text'>Contrôler le temps d&#39;execution maximum d&#39;un traitement PHP</title><content type='html'>&lt;p&gt;Il est parfois nécessaire d&#39;exécuter un traitement PHP avec une contrainte de temps maximum à ne pas dépasser. Dans cette article je vais vous proposer une solution à ce problème.&lt;/p&gt;

&lt;p&gt;Voici un petit exemple impossible que nous allons tenter d&#39;implémenter : &quot;Faites ce que vous voulez dans une boucle infinie. Si au bout de 5 secondes vous n&#39;avez pas terminé, stoppez le traitement&quot;.&lt;/p&gt;

&lt;p&gt;Voici une classe qui va s&#39;occuper de ce travail :&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;
class   MissionImpossible
{
  public function start()
  {
    while (42)
      {
        echo &quot;processing nothing...\n&quot;;
        sleep(1);
      }
  }

  public function abort()
  {
    throw new Exception(&quot;Time limit ! job aborted&quot;);
  }
}
&lt;/pre&gt;


&lt;p&gt;Maintenant, passons aux choses intéressantes : comment s&#39;y prendre pour appeler la fonction &lt;i&gt;abort()&lt;/i&gt; au bout de 5 secondes, alors que la fonction start() est en train de s&#39;executer ?&lt;/p&gt;

&lt;p&gt;Nous allons utiliser le mécanisme de &lt;a href=&quot;http://en.wikipedia.org/wiki/Signal_(computing)&quot;&gt;signaux POSIX&lt;/a&gt; pour interrompre le processus et l&#39;informer que le temps qui lui était alloué arrive à terme. Le signal &lt;a href=&quot;http://fr.wikipedia.org/wiki/SIGALRM&quot;&gt;SIGALRM&lt;/a&gt; est parfaitement adapté à ce cas d&#39;utilisation.&lt;/p&gt;

&lt;p&gt;Deux fonctions vont nous être utiles en PHP :
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.php.net/pcntl_signal&quot;&gt;pcntl_signal&lt;/a&gt; qui permet de definir quelle fonction va etre appelée lorsqu&#39;un signal particulier est reçu.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.php.net/pcntl_alarm&quot;&gt;pcntl_alarm&lt;/a&gt; qui permet de mettre en place un compte a rebours, qui lorsqu&#39;il est terminé envoie un signal SIGALRM au processus courant.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;


Voici donc comment résoudre notre problème :

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;
declare(ticks = 1);
require(&#39;MissionImpossible.php&#39;);

$job = new MissionImpossible();
pcntl_signal(SIGALRM, array($job, &quot;abort&quot;), true);
pcntl_alarm(5);
try {
  $job-&gt;start();
}
catch (Exception $e)
{
  echo &quot;Exception caught. Stopping execution\n&quot;;
}
&lt;/pre&gt;

&lt;p&gt;Quelques commentaires :
&lt;ul&gt;
&lt;li&gt;&lt;u&gt;Lignes 1 et 2 :&lt;/u&gt; l&#39;appel à la fonction &lt;a href=&quot;http://www.php.net/declare&quot;&gt;declare&lt;/a&gt; est indispensable pour que le mécanisme de signaux puisse fonctionner en PHP. Il doit être fait impérativement avant la déclaration de la classe MissionImpossible.&lt;/li&gt;
&lt;li&gt;&lt;u&gt;Ligne 5 :&lt;/u&gt; mise en place du gestionnaire de signaux : la fonction abort() de l&#39;instance $job de la classe MissionImpossible sera appelée dès qu&#39;un signal SIGALRM sera reçu&lt;/li&gt;
&lt;li&gt;&lt;u&gt;Ligne 6 :&lt;/u&gt; mise en place du compte à rebours. Dans 5 secondes, un signal SIGALRM sera envoyé au processus courant&lt;/li&gt;
&lt;li&gt;Dans la fonction abort(), une exception est lancée. Sans elle, le traitement de la fonction start() aurait continué dès la fin de la fonction abort().&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Voilà, c&#39;est tout simple. Mais sachez que les fonctions de l&#39;extension pcntl ont quelques inconvénients : (&lt;a href=&quot;http://www.php.net/manual/fr/intro.pcntl.php&quot;&gt;cf doc officielle&lt;/a&gt;)
&lt;ul&gt;
  &lt;li&gt;&quot;Cette extension ne doit pas être activée pour une utilisation en serveur web, car les résultats pourraient être inattendus&quot;&lt;/li&gt;
  &lt;li&gt;&quot;Cette extension n&#39;est pas disponible sur les plates-formes Windows.&quot;&lt;/li&gt;
&lt;/ul&gt;
Si cela vous pose problème, regardez du coté de &lt;a href=&quot;http://www.php.net/register_tick_function&quot;&gt;register_tick_function&lt;/a&gt; (qui a lui aussi quelques inconvenients :  &quot; [...] ne doit pas être utilisé avec les modules de serveur web threadé. Les ticks ne fonctionnent pas en mode ZTS et peuvent interrompre votre serveur web.&quot;)&lt;/p&gt;

&lt;p&gt;Enfin, cet exemple était vraiment simpliste mais sachez que c&#39;est applicable pour tout traitement lourd et &quot;réversible&quot; (par exemple une grosse transaction MySQL).&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigornot-fr.blogspot.com/feeds/2919322773834557308/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3073819899020661481/2919322773834557308' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/2919322773834557308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/2919322773834557308'/><link rel='alternate' type='text/html' href='http://bigornot-fr.blogspot.com/2008/11/contrler-le-temps-dexecution-maximum.html' title='Contrôler le temps d&#39;execution maximum d&#39;un traitement PHP'/><author><name>Mat</name><uri>http://www.blogger.com/profile/15945738194810734875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3073819899020661481.post-1798250133254961077</id><published>2008-09-26T23:01:00.005+02:00</published><updated>2008-09-26T23:31:46.249+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ergonomie"/><category scheme="http://www.blogger.com/atom/ns#" term="idees"/><title type='text'>Parlons d&#39;ergonomie</title><content type='html'>&lt;p&gt;L&#39;une des règles d&#39;ergonomie à appliquer lorsque l&#39;on fait un site web est d&#39;utiliser un vocabulaire standard pour que les visiteurs ne soient pas perdus. Mais... comment choisir correctement ses mots ?&lt;/p&gt;

&lt;p&gt;La méthode classique : constituer une liste de mots &quot;éligibles&quot;, parcourir le web pour trouver lesquels sont les plus populaires, puis enfin faire son choix. Au fur et à mesure, on accumule de l&#39;expérience et se fait son propre dictionnaire de mots à utiliser.&lt;/p&gt;

&lt;p&gt;Ne serait-il pas intéressant de cumuler nos expériences sur un site qui servirait de dictionnaire de référence en la matière ? Fonctionnant de la même manière qu&#39;un dictionnaire de synonymes, il pourrait pour chaque mot donner les alternatives possibles et leur popularité, ainsi qu&#39;une liste de sites qui les utilise. Ce serait un gain de temps pour nous tous.&lt;/p&gt;

&lt;p style=&quot;text-decoration: underline&quot;&gt;Exemple:&lt;/p&gt;

&lt;div style=&quot;margin: 1.5em 2em; padding: 0.5em; border: 1px solid black&quot;&gt;
&lt;div style=&quot;text-decoration: underline&quot;&gt;Deconnexion&lt;/div&gt;
&lt;div style=&quot;color:green&quot;&gt;Utilisation recommandée&lt;/div&gt;
&lt;div&gt;Alternatives:   &lt;span style=&quot;color:green&quot;&gt;Quitter&lt;/span&gt;, &lt;span style=&quot;color:red&quot;&gt;Va-voir-ailleurs-si-j&#39;y-suis!&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Si ce service existe déjà, merci de me donner l&#39;URL ;-) Sinon je trouve que ce serait un bon projet... Je n&#39;ai malheureusement pas le temps de me lancer dessus. Si ça tente quelqu&#39;un, l&#39;idée attend au chaud !&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigornot-fr.blogspot.com/feeds/1798250133254961077/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3073819899020661481/1798250133254961077' title='2 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/1798250133254961077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/1798250133254961077'/><link rel='alternate' type='text/html' href='http://bigornot-fr.blogspot.com/2008/09/parlons-dergonomie.html' title='Parlons d&#39;ergonomie'/><author><name>Mat</name><uri>http://www.blogger.com/profile/15945738194810734875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3073819899020661481.post-6055980554959638334</id><published>2008-07-05T14:02:00.018+02:00</published><updated>2013-06-17T11:35:50.910+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="csrf"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="sécurité"/><category scheme="http://www.blogger.com/atom/ns#" term="zend framework"/><title type='text'>CSRF : Sea, Surf and Zend</title><content type='html'>&lt;p style=&quot;font-style: italic;&quot;&gt;&lt;u&gt;Note:&lt;/u&gt; Si vous n&#39;utilisez pas Zend Framework et que le titre vous a fait peur, ne fuyez pas, je ne parle de ZF qu&#39;à la fin.&lt;/p&gt;&lt;p&gt;Au programme d&#39;aujourd&#39;hui, un peu de prévention ! Comme vous l&#39;avez remarqué, l&#39;été pointe enfin le bout de son nez et il devient difficile de rester concentré devant son écran. On parle souvent d&#39;insolations, de déshydratations, mais n&#39;oubliez pas non plus qu&#39;&lt;a href=&quot;http://www.youtube.com/watch?v=H6awXw_baxY&quot;&gt;une seule seconde d&#39;inattention&lt;/a&gt; peut mener à une faille de sécurité dans votre code ! &lt;/p&gt;&lt;p&gt;C&#39;est pourquoi j&#39;aimerais vous parler des failles de type &lt;a href=&quot;http://fr.wikipedia.org/wiki/Cross-Site_Request_Forgeries&quot;&gt;CSRF&lt;/a&gt;. Si cela ne vous évoque rien ou pas grand chose, je vous conseille d&#39;aller vous renseigner sur le sujet, &lt;a href=&quot;http://www.google.fr/search?q=csrf&quot;&gt;de nombreux articles expliquent le problème&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;Comment s&#39;en protéger ? Tout d&#39;abord je vous conseillerais de boire de l&#39;eau (sans aucun additif anisé) lorsque vous codez. Mais ça ne suffit pas ! Les techniques suivantes sont souvent utilisées pour se protéger contre les CSRF : &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Utiliser la méthode HTTP &lt;b&gt;POST&lt;/b&gt; (ou UPDATE ou DELETE) pour toutes les actions qui ne sont pas de la consultation de ressource (insertion, mise à jour ou suppression).  D&#39;une part, vous protégera légèrement contre le CSRF, d&#39;autre part ça sera le premier pas vers une architecture &lt;a href=&quot;http://www.biologeek.com/rest,traduction,web-semantique/pour-ne-plus-etre-en-rest-comprendre-cette-architecture/&quot;&gt;RESTful&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Utiliser des token de sécurité (aussi appelés &lt;i&gt;nonce&lt;/i&gt; ou encore &lt;i&gt;bordel pour paranoïaque&lt;/i&gt;)  Kézako ? En gros lorsqu&#39;un utilisateur affiche un formulaire, on lui génère une clé. Cette clé sera valide pour un certain temps (5 min en général), sera liée uniquement au couple utilisateur/formulaire et devra automatiquement être transmise avec le formulaire pour que celui ci puisse être validé !  &lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;En général, cela évite les dégats.  Par contre méfiez vous car si vous êtes également vulnérable à une faille de type &lt;a href=&quot;http://fr.wikipedia.org/wiki/Cross_site_scripting&quot;&gt;XSS&lt;/a&gt;, ces protections ne changeront absolument rien ! Ce serait aussi efficace que d&#39;installer une porte blindée à la place de la fermeture d&#39;une tente de camping en toile. Un simple cure dent permettrait de désintégrer votre site web.  &lt;/p&gt;&lt;p&gt;Donc techniquement, pour se protéger, il faut agir à deux niveaux :  &lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;div&gt;Affichage du formulaire&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Générer un token valide pour cet utilisateur et ce formulaire &lt;a href=&quot;http://www.blogger.com/post-edit.g?blogID=3073819899020661481&amp;amp;postID=6055980554959638334#ref1&quot;&gt;[1]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stocker ce token quelque part &lt;a href=&quot;http://www.blogger.com/post-edit.g?blogID=3073819899020661481&amp;amp;postID=6055980554959638334#ref2&quot;&gt;[2]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ajouter la valeur du token dans un champ caché du formulaire &lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;div&gt;Validation du formulaire&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Ne traiter que les données qui ont ete envoyées par POST (ou UPDATE ou DELETE)&lt;/li&gt;
&lt;li&gt;Récupérer le token valide quelque part &lt;a href=&quot;http://www.blogger.com/post-edit.g?blogID=3073819899020661481&amp;amp;postID=6055980554959638334#ref2&quot;&gt;[2]&lt;/a&gt; et vérifier qu&#39;il n&#39;est pas expiré&lt;/li&gt;
&lt;li&gt;Comparer ce token à celui qui a été POSTé    &lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Simple, non ? Étudions maintenant deux points :  &lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;div&gt;&lt;a name=&quot;ref1&quot;&gt;&lt;span style=&quot;font-size:150;&quot;&gt;Comment genérer le token ?&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;   Le token ne doit pas être prédictible.     Je vous propose d&#39;utiliser la formule suivante :      &lt;/p&gt;&lt;div&gt;&lt;b&gt;MD5( identifiant_formulaire . server_secret . assaisonnement)&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;identifiant_formulaire&lt;/b&gt; est une chaîne représentant le formulaire concerné&lt;/div&gt;&lt;div&gt;&lt;b&gt;server_secret&lt;/b&gt; est une clé connue uniquement par le serveur&lt;/div&gt;&lt;div&gt;&lt;b&gt;assaisonnement&lt;/b&gt; est un nombre aléatoire (entre 1 et beaucoup, par exemple)&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;div&gt;&lt;a name=&quot;ref2&quot;&gt;&lt;span style=&quot;font-size:150;&quot;&gt;Où stocker le token entre le moment de l&#39;affichage et la validation du formulaire ?&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;Tout est possible, tout est imaginable...   &lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://fr.php.net/manual/en/ref.session.php&quot;&gt;Sessions natives PHP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.danga.com/memcached&quot;&gt;Memcache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Base de données (MySQL, Postgresql, sqlite, Berkeley DB, &lt;a href=&quot;http://memcachedb.org/&quot;&gt;Memcachedb&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bigornot-fr.blogspot.com/2008/06/scurisation-des-cookies-une.html&quot;&gt;Cookie sécurisé&lt;/a&gt; (c&#39;était juste pour les citer mais je vous les déconseille pour cette utilisation. Si vous avez beaucoup de formulaires ça va créer beaucoup de données qui transiteront entre l&#39;utilisateur et le serveur à chaque requête)&lt;/li&gt;
&lt;/ul&gt;... à condition bien sur que personne ne puisse altérer les données que vous y avez stocké.  &lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Si sauvegarder les token en session vous convient, le &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt; propose une solution qui fait exactement tout ça : &lt;a href=&quot;http://framework.zend.com/apidoc/core/Zend_Form/Element/Zend_Form_Element_Hash.html&quot;&gt;Zend_Form_Element_Hash&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;Moi je n&#39;aime toujours pas les sessions, donc je vais préférer Memcache pour y stocker les token. Memcache fournit nativement le système d&#39;expiration, c&#39;est rapide, et c&#39;est pratique a utiliser dans un environnement multi-serveur.  Note: Il y a un risque que certains token soient perdu, compte tenu du &lt;a href=&quot;http://www.eu.socialtext.net/memcached/index.cgi?faq#what_is_memcached_s_cache&quot;&gt;mode de fonctionnement de Memcache&lt;/a&gt;. Mais je vais prendre ce risque compte tenu de leur faible durée de vie. De plus, je vais surveiller l&#39;utilisation de mémoire de memcache pour éviter le problème. &lt;/p&gt;J&#39;ai donc créé une classe qui ressemble beaucoup à Zend_Form_Element_Hash, sauf qu&#39;elle implémente un mécanisme de &quot;Storage Adapter&quot; qui permet de stocker les tokens n&#39;importe où. J&#39;ai également créé un Adapter qui permet de stocker les données dans Memcache, mais libre à vous de créer les Adapter de vos rêves (j&#39;étudie actuellement une solution de stockage des token dans un bigorneaux fossilisé, mais c&#39;est pas très scalable).  &lt;p&gt;&lt;a href=&quot;http://dl.huguet.eu/bigornot/BigOrNot_Form_Element_Token.tgz&quot;&gt;C&#39;est ici pour télécharger les classes BigOrNot_Form_Element_Token*&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Exemple d&#39;utilisation :  &lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;// Initialisation du formulaire
$form = new Zend_Form ...

// Initialisation de Memcache
$memcache = new Memcache ...

// Recuperation de l&#39;identifiant de l&#39;utilisateur
$uniqueUserID = Zend_Auth::getIdentity();

// Mise en place du token de protection
$storage = new BigOrNot_Form_Element_Token_Storage_Memcache($memcache, $uniqueUserID);
$tokenElement = new BigOrNot_Form_Element_Token(&#39;formulaire_ajout_bigorneaux&#39;, array(&#39;adapter&#39; =&gt; $storage));
$form-&gt;addElement($tokenElement);
&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Enjoy !&lt;/p&gt;&lt;p&gt;Pour conclure, une petite quote d&#39;un papier (&lt;a href=&quot;http://esl.epitech.net/acsrf/2008-Epitech-SecurityLab_AdvancedCSRF.pdf&quot;&gt;Advanced CRSF&lt;/a&gt;) de l&#39;&lt;a href=&quot;http://esl.epitech.net/main/&quot;&gt;Epitech Security Lab&lt;/a&gt;  :&lt;/p&gt;&lt;p style=&quot;font-style: italic; margin-left: 2em;&quot;&gt;Tant que le développement web sera fait par des gens non sensibilisés aux plus évidentes règles de sécurité, que des langages à pièges comme PHP seront “maitrisés” entre deux cours de géographie, il va falloir se faire à l’idée de surfer avec netcat et lire ses mails avec gnus. &lt;/p&gt;&lt;p&gt;Une solution ? &lt;a href=&quot;http://digg.com/submit?phase=2&amp;amp;url=http://bigornot-fr.blogspot.com/2008/07/csrf-sea-surf-and-zend.html&quot;&gt;Faites circuler cet article&lt;/a&gt; dans la boîte au lettre de tous vos voisins (sinon votre serveur Web va perdre ses dents et votre système va mourir d&#39;un kill -9 -1)&lt;/p&gt;;-)</content><link rel='replies' type='application/atom+xml' href='http://bigornot-fr.blogspot.com/feeds/6055980554959638334/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3073819899020661481/6055980554959638334' title='5 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/6055980554959638334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/6055980554959638334'/><link rel='alternate' type='text/html' href='http://bigornot-fr.blogspot.com/2008/07/csrf-sea-surf-and-zend.html' title='CSRF : Sea, Surf and Zend'/><author><name>Mat</name><uri>http://www.blogger.com/profile/15945738194810734875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3073819899020661481.post-7275821310165292488</id><published>2008-06-23T09:44:00.008+02:00</published><updated>2013-06-17T11:36:14.566+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="memcache"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="sécurité"/><title type='text'>Une classe de protection contre le flood</title><content type='html'>&lt;p&gt;Il est très courant d&#39;être victime de flood pour certaines fonctionnalités proposées par votre site.&lt;/p&gt;Exemples : &lt;ul&gt;&lt;li&gt;Commentaires sur votre blog&lt;/li&gt;
&lt;li&gt;Posts sur votre forum&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jura.com/home_x/products_home_use/f_line/impressa_f90.htm&quot;&gt;Café court sans sucre sur votre cafetière réseau&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;...etc&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Que penseriez vous d&#39;une classe qui permettrait de bloquer (ou plutôt ralentir) les tentatives de flood sur les fonctionnalités sensibles de votre site ? (ex: pas plus d&#39;1 post sur le forum toutes les 30 secondes).&lt;/p&gt;&lt;p&gt;Pour cela, nous allons utiliser &lt;a href=&quot;http://danga.com/memcached/&quot;&gt;memcache&lt;/a&gt;. Si vous ne connaissez pas memcache, c&#39;est un système de cache distribué extrèmement rapide. Comme tout système de cache, il offre un mécanisme de stockage, de récupération et d&#39;expiration des données.&lt;/p&gt;&lt;p&gt;Pourquoi memcache ?&lt;br /&gt;
C&#39;est un outil pratique aussi bien dans un environnement multiserveur que sur un seul serveur, donc il est accessible à un grand nombre de personnes (désolé ca n&#39;inclu pas les comptes de type &quot;mutualisés&quot; grand public).&lt;br /&gt;
Il propose également un mécanisme d&#39;expiration qui correspond parfaitement à nos besoins pour ce système de flood-control. &lt;/p&gt;&lt;p&gt;&lt;u&gt;Principe :&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.php.net/memcache&quot;&gt;l&#39;extension memcache pour PHP&lt;/a&gt; propose une fonction &lt;a href=&quot;http://www.php.net/memcache-add&quot;&gt;Memcache::add()&lt;/a&gt; qui permet d&#39;ajouter une donnee au cache &lt;b&gt;si et seulement si celle-ci n&#39;existe pas déjà&lt;/b&gt;.&lt;br /&gt;
A chaque action d&#39;un utilisateur que nous voulons limiter, il suffit donc d&#39;ajouter une information dans le cache avec une date d&#39;expiration correspondant au temps d&#39;attente necessaire avant la prochaine action. Si la fonction add() renvoie une erreur, c&#39;est qu&#39;une action a déjà été effectuée durant cette intervalle de temps.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Scénario type :&lt;/u&gt; (flood control sur un forum, 1 post toutes les 30 sec)&lt;br /&gt;
11:00:00 : jean-craoude much poste un message sur le forum. Le forum ajoute une entrée au cache qui a pour ID &quot;ForumPost:JeanCraoudeMuch&quot; et pour date d&#39;expiration 30 secondes.&lt;br /&gt;
11:00:15 : jean-craoude Much s&#39;endort malencontreusement sur la touche F5 de son clavier. Toutes les nanosecondes, une requête est donc envoyée au serveur pour poster à nouveau le même message. Le forum va donc pour chaque requête tenter de remettre en cache une donnée ayant pour ID &quot;ForumPost:JeanCraoudeMuch&quot;, mais celle-ci existant déjà, la fonction Memcache::add() va renvoyer une erreur. Le post sera donc refusé.&lt;br /&gt;
11:00:29 : jean-craoude Much se réveille et se regarde dans le mirroir. Voyant un F5 rouge se dessiner sur son front, il se précipite sur le forum pour voir l&#39;etendue de ses dégats. Fort heureusement, tout va bien, il est rassuré. Il se rendort donc consciencieusement, mais cette fois-ci à côté du clavier&lt;/p&gt;&lt;p&gt;Bref, si vous êtes séduit par ce système, voici une petite classe qui vous permettra de le mettre en place très facilement : &lt;a href=&quot;http://dl.huguet.eu/bigornot/FloodControl.tar.gz&quot;&gt;BigOrNot_FloodControl&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Exemple d&#39;utilisation :&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;/* Initialisation d&#39;un objet memcache */
$cache = new Memcache;
$cache-&gt;addServer(&#39;127.0.0.1&#39;);

/* Initialisation de la classe flood control */
$floodControl = new BigOrNot_FloodControl($cache);

/* ... */

/* Utilisation de la classe pour limiter les posts dans un forum */
$userId = Forum::getUserId();
if ($floodControl-&gt;isAllowed(&#39;posterUnMessageDansLeForum&#39;, $userId, 30))
{
    posterMessage();
}
else
{
    messageErreur();
}

&lt;/pre&gt;&lt;p&gt;Voila, c&#39;est simple et efficace. Inutile de s&#39;armer d&#39;une base de données pour ce genre de choses.&lt;/p&gt;&lt;p&gt;Notes : &lt;ul&gt;&lt;li&gt;Avec cette solution, il n&#39;y a pas la possibilité de faire des restrictions avec une intervalle inférieure à 1 seconde. Pour les amateurs de nanosecondes, cela nécessitera quelques modifications.&lt;/li&gt;
&lt;li&gt;Je n&#39;ai pas utilisé Zend_Cache car je n&#39;ai pas trouvé de mécanisme équivalent au add() de Memcache. Il y a probablement moyen de mettre en place un système de lock qui y ressemblerait, mais ca ne m&#39;enchantait pas trop... Alors si l&#39;envie vous prend, n&#39;hesitez pas ;) Méfiez vous des appels simultanés à votre système&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigornot-fr.blogspot.com/feeds/7275821310165292488/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3073819899020661481/7275821310165292488' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/7275821310165292488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/7275821310165292488'/><link rel='alternate' type='text/html' href='http://bigornot-fr.blogspot.com/2008/06/une-classe-de-protection-contre-le.html' title='Une classe de protection contre le flood'/><author><name>Mat</name><uri>http://www.blogger.com/profile/15945738194810734875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3073819899020661481.post-4192512446235525467</id><published>2008-06-15T22:18:00.011+02:00</published><updated>2013-06-17T11:36:29.043+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cookies"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="sécurité"/><category scheme="http://www.blogger.com/atom/ns#" term="zend framework"/><title type='text'>Zend_Auth et le cookie masqué</title><content type='html'>&lt;p&gt;Je vais encore vous parler de cookies, mais cette fois-ci à la sauce Zend_Auth.&lt;/p&gt;&lt;p&gt;Je vous ai présenté dans &lt;a href=&quot;http://bigornot-fr.blogspot.com/2008/06/scurisation-des-cookies-une.html&quot;&gt;un précédent article&lt;/a&gt; une classe permettant de gérer des &lt;a href=&quot;http://bigornot-fr.blogspot.com/2008/06/introduction-la-scurit-des-cookies.html&quot;&gt;cookies sécurisés&lt;/a&gt;. Maintenant nous allons voir comment l&#39;utiliser dans un cas très courant : l&#39;authentification avec Zend_Auth.&lt;/p&gt;&lt;p&gt;Rappelons les grandes lignes de Zend_Auth :&lt;/p&gt;&lt;ul&gt;&lt;li&gt;On s&#39;authentifie d&#39;une certaine façon (avec &lt;a href=&quot;http://framework.zend.com/apidoc/core/Zend_Auth/Zend_Auth_Adapter/Zend_Auth_Adapter_DbTable.html&quot;&gt;une base de données&lt;/a&gt;, &lt;a href=&quot;http://framework.zend.com/apidoc/core/Zend_Auth/Zend_Auth_Adapter/Zend_Auth_Adapter_Digest.html&quot;&gt;un fichier&lt;/a&gt;, &lt;a href=&quot;http://framework.zend.com/apidoc/core/Zend_Auth/Zend_Auth_Adapter/Zend_Auth_Adapter_Ldap.html&quot;&gt;un annuaire LDAP&lt;/a&gt;, &lt;a href=&quot;http://framework.zend.com/apidoc/core/Zend_Auth/Zend_Auth_Adapter/Zend_Auth_Adapter_OpenId.html&quot;&gt;un provider OpenID&lt;/a&gt;... etc). Celle-ci est définie par un &quot;Adapter&quot;, c&#39;est à dire n&#39;importe quelle classe qui implémente l&#39;interface &lt;a style=&quot;font-weight: bold;&quot; href=&quot;http://framework.zend.com/apidoc/core/Zend_Auth/Zend_Auth_Adapter/Zend_Auth_Adapter_Interface.html&quot;&gt;Zend_Auth_Adapter_Interface&lt;/a&gt;.  &lt;/li&gt;
&lt;li&gt;Une fois authentifié, il faut stocker son identité. Par défaut l&#39;identité est stockée en session, mais il suffit de créer une classe implémentant l&#39;interface &lt;a href=&quot;http://framework.zend.com/apidoc/core/Zend_Auth/Zend_Auth_Storage/Zend_Auth_Storage_Interface.html&quot;&gt;Zend_Auth_Storage_Interface&lt;/a&gt; pour la stocker où bon vous semble. Et c&#39;est ce que nous allons faire ! &lt;/li&gt;
&lt;/ul&gt;Si comme moi vous n&#39;utilisez les sessions que pour stocker l&#39;identité des utilisateurs authentifiés (leur identifiant, un simple nombre entier en général), vous allez peut être trouver que c&#39;est du gachi. Les sessions c&#39;est lourd et ennuyeux à gérer quand l&#39;application en question tourne sur une ferme de serveurs web (qui font meuh meuh en core et en core).  &lt;p&gt;Bref, ne serait-il pas tentant de déléguer cette tâche au client ? Qu&#39;il présente lui même son identité ? C&#39;est risqué vous allez dire... et vous avez raison !&lt;br /&gt;
On peut déjà imaginer les pires scénarios :&lt;/p&gt;&lt;div&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Serveur&gt;&lt;/span&gt; Bien le bonjour ! A qui ai-je l&#39;honneur ?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Client (de type malicieux)&gt;&lt;/span&gt; Je suis l&#39;administrateur du site ! Regarde j&#39;ai... ma bonne parole pour te le prouver !&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Serveur&gt;&lt;/span&gt; Salut chef je t&#39;avais pas reconnu. Voici les clefs de ton royaume.&lt;/span&gt;&lt;/div&gt;&lt;p&gt;Techniquement, ca reviendrait a stocker l&#39;user_id dans un cookie et de faire complètement confiance à ce cookie.&lt;/p&gt;&lt;p&gt;En général ce genre de scénarios est très peu apprécié par le public (en particulier celui de votre site). Donc on va tenter d&#39;utiliser quelques ruses cryptographiques pour confier à l&#39;utilisateur le soin de présenter son identité, sans qu&#39;il puisse la modifier : on va la stocker dans un cookie sécurisé grâce à la classe BigOrNot_CookieManager.&lt;/p&gt;&lt;p&gt;J&#39;ai donc écrit une classe qui implémente l&#39;interface Zend_Auth_Storage_Interface pour stocker l&#39;identité des utilisateurs dans un cookie sécurisé.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://dl.huguet.eu/bigornot/Cookie.tar.gz&quot;&gt;Vous pouvez la télécharger ici (l&#39;archive contient également la classe BigOrNot_CookieManager)&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Voici comment l&#39;utiliser :&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;$cookieManager = new BigOrNot_CookieManager(&#39;SECRET_KEY&#39;);
$authStorage = new BigOrNot_Auth_Storage_Cookie($cookieManager);
$auth = Zend_Auth::getInstance();
$auth-&gt;setStorage($authStorage);

[...]
&lt;/pre&gt;&lt;p&gt;Par defaut, le cookie s&#39;appelle &quot;auth&quot; et les paramètres par défaut sont envoyes a &lt;a href=&quot;http://www.php.net/setcookie&quot;&gt;setcookie()&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Si vous souhaitez modifier ces paramètres, il est possible d&#39;envoyer au constructeur de la classe BigOrNot_Auth_Storage_Cookie un deuxième paramètre : un tableau (ou un objet Zend_Config) de configuration.&lt;/p&gt;&lt;p&gt;Les paramètres de configuration supportés sont : cookieName, cookieExpire, cookiePath, cookieDomain, cookieSecure, cookieHttpOnly. (Les noms sont assez explicites, voir la doc de &lt;a href=&quot;http://www.php.net/setcookie&quot;&gt;setcookie()&lt;/a&gt; si vous avez des doutes).&lt;/p&gt;&lt;p&gt;&lt;u&gt;Exemple d&#39;utilisation avec configuration :&lt;/u&gt;&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;$cookieManager = new BigOrNot_CookieManager(&#39;SECRET_KEY&#39;);

$storageConfig = array(
    &#39;cookieName&#39; =&gt; &#39;BigOrNauth&#39;,
    &#39;cookieExpire&#39; =&gt; (time() + 3600),
    &#39;cookiePath&#39; =&gt; &#39;/&#39;,
    &#39;cookieDomain&#39; =&gt; &#39;bigornot-fr.blogspot.com&#39;
);

$authStorage = new BigOrNot_Auth_Storage_Cookie($cookieManager, $storageConfig);
$auth = Zend_Auth::getInstance();
$auth-&gt;setStorage($authStorage);
&lt;/pre&gt;&lt;p&gt;L&#39;identité est stockée &quot;&lt;a href=&quot;http://www.php.net/serialize&quot;&gt;serialisée&lt;/a&gt;&quot; donc vous pouvez y stocker toute valeur serialisable. Evitez tout de même les gros objets, les cookies trop gros sont vite écoeurants. N&#39;oubliez pas qu&#39;ils sont transmis à chaque requête.&lt;/p&gt;&lt;p&gt;L&#39;identité est également stockée chiffrée, donc vous ne donnez aucune information confidentielle à l&#39;utilisateur en utilisant cette technique.&lt;/p&gt;&lt;p&gt;&lt;u&gt;Pour information :&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;http://bigornot-fr.blogspot.com/2008/06/scurisation-des-cookies-une.html&quot;&gt;Comme nous l&#39;avons vu dans le précédent article&lt;/a&gt;, pour la methode BigOrNot_CookieManager::setCookie(), il est necessaire d&#39;envoyer en paramètre un nom d&#39;utilisateur (ou n&#39;importe quel identifiant unique).&lt;br /&gt;
Dans la classe BigOrNot_Auth_Storage_Cookie, j&#39;envoie un hash md5 de l&#39;identite serialisee. &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigornot-fr.blogspot.com/feeds/4192512446235525467/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3073819899020661481/4192512446235525467' title='2 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/4192512446235525467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/4192512446235525467'/><link rel='alternate' type='text/html' href='http://bigornot-fr.blogspot.com/2008/06/la-revanche-de-zendauth-contre-le.html' title='Zend_Auth et le cookie masqué'/><author><name>Mat</name><uri>http://www.blogger.com/profile/15945738194810734875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3073819899020661481.post-604258152690233464</id><published>2008-06-13T15:15:00.002+02:00</published><updated>2013-06-17T11:36:48.614+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cookies"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="sécurité"/><title type='text'>Sécurisation des cookies : une implementation en PHP</title><content type='html'>&lt;p  style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Note pour les nouveaux arrivants :&lt;/span&gt; vous devriez lire avant tout le précedent article : &lt;a href=&quot;http://bigornot-fr.blogspot.com/2008/06/introduction-la-scurit-des-cookies.html&quot;&gt;Introduction à la sécurité des cookies.&lt;/a&gt;&lt;a href=&quot;http://bigornot.blogspot.com/2008/06/security-cookies-and-rest.html&quot;&gt; &lt;/a&gt;&lt;/p&gt;&lt;p&gt;Donc... où en étions nous ? Il existe un protocole de sécurisation des cookies (&lt;span style=&quot;font-size:85%;&quot;&gt;voir &lt;a href=&quot;http://www.cse.msu.edu/%7Ealexliu/publications/Cookie/cookie.pdf&quot;&gt;le papier de Alex X. Liu pour les details&lt;/a&gt;&lt;/span&gt;) :&lt;/p&gt;&lt;div style=&quot;border: 1px solid rgb(192, 192, 192); padding: 5px;&quot;&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;Cookie value = &lt;/span&gt; &lt;blockquote&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;span style=&quot;color: rgb(0, 102, 0);&quot;&gt;username&lt;/span&gt;|&lt;span style=&quot;color: rgb(255, 102, 0);&quot;&gt;expiration time&lt;/span&gt;|(&lt;span style=&quot;color: rgb(204, 153, 51);&quot;&gt;data&lt;/span&gt;)&lt;span style=&quot;color: rgb(102, 0, 204);&quot;&gt;k&lt;/span&gt;|HMAC(&lt;span style=&quot;color: rgb(0, 102, 0);&quot;&gt;username&lt;/span&gt;|&lt;span style=&quot;color: rgb(204, 102, 0);&quot;&gt;expiration time&lt;/span&gt;|&lt;span style=&quot;color: rgb(204, 153, 51);&quot;&gt;data&lt;/span&gt;|&lt;span style=&quot;color: rgb(102, 51, 51);&quot;&gt;SSL session key&lt;/span&gt;, &lt;span style=&quot;color: rgb(102, 0, 204);&quot;&gt;k&lt;/span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Avec&lt;/span&gt;  &lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;span style=&quot;color: rgb(0, 102, 0);&quot;&gt;username&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt; est le nom de l&#39;utilisateur (ou un identifiant unique)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;span style=&quot;color: rgb(255, 102, 0);&quot;&gt;expiration time&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt; est la data d&#39;expiration du cookie &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;(&lt;span style=&quot;color: rgb(204, 153, 51);&quot;&gt;data&lt;/span&gt;)&lt;span style=&quot;color: rgb(102, 0, 204);&quot;&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt; est le résultat d&#39;une function de chiffrement par bloc (ex: AES) de &lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;span style=&quot;color: rgb(204, 153, 51);&quot;&gt;data&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt; avec la clé &lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;span style=&quot;color: rgb(102, 0, 204);&quot;&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;span style=&quot;color: rgb(204, 153, 51);&quot;&gt;data&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt; est la donnée que vous souhaitez stocker dans le cookie &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;span style=&quot;color: rgb(102, 0, 204);&quot;&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt; est le résultat de la fonction HMAC(&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;span style=&quot;color: rgb(0, 102, 0);&quot;&gt;username&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;span style=&quot;color: rgb(255, 102, 0);&quot;&gt;expiration time&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;, &lt;span style=&quot;color: rgb(102, 102, 204);&quot;&gt;sk&lt;/span&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;color: rgb(102, 102, 204);&quot;&gt;sk&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt; est une clé secrète que seul le serveur connait &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;span style=&quot;color: rgb(102, 51, 51);&quot;&gt;SSL session key&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt; est l&#39;identifiant de la session SSL en cours.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt; &lt;/span&gt; &lt;/div&gt;&lt;p&gt;Ce protocole est sécurisé : &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Il protège vos cookies contre les &quot;replay attacks&quot;&lt;/span&gt; : L&#39;identifiant de la session SSL en cours est unique. Si un utilisateur malicieux essaie d&#39;envoyer le cookie d&#39;un autre dans une autre session SSL, le cookie sera invalide.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Il protège la confidentialité des données &lt;/span&gt; grâce à une fonction de chiffrement symmétrique : les données sont stockées sous une forme chiffrées. &lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Il protège l&#39;intégrité des données&lt;/span&gt; grâce à une fonction HMAC &lt;/li&gt;
&lt;li style=&quot;font-weight: bold;&quot;&gt;Il protège la clé secrète du serveur contre les &quot;volume attack&quot; :&lt;span style=&quot;font-weight: normal;&quot;&gt; le fait d&#39;inclure le nom de l&#39;utilisateur et la date d&#39;expiration dans la clé k permet d&#39;éviter qu&#39;un analyste malicieux s&#39;amuse à créer un grand nombre de cookies sécurités pour essayer de retrouvé la clé secrète stockée sur le serveur.&lt;/span&gt; &lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Cependant, ce protocole n&#39;est pas adapté à tous les usages : &lt;/p&gt;&lt;ol&gt;&lt;li&gt;SSL c&#39;est chouette, ça protège contre les replay attacks, mais : &lt;ul&gt;&lt;li&gt;Votre application n&#39;est pas forcément accessible en HTTPS &lt;/li&gt;
&lt;li&gt;La durée de vie du cookie est limitée à celle de la session SSL. &lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Le chiffrement des données stockées dans le cookie, c&#39;est cool, mais ça ne vous interresse pas forcement ! Si vous n&#39;en avez pas l&#39;utilité, ça va augmenter la taille du cookie pour rien. &lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;Par exemple : si les données sont chiffrées avec en AES256, la valeur chiffrée fera au moins 32 octets, même si  les données en clair ne font d&#39;1 octet !&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Donc il serait cool d&#39;avoir une classe de gestion des cookies qui puisse être configurable, c&#39;est à dire qui offrirait la possibilité de : &lt;/p&gt;&lt;ul&gt;&lt;li&gt;activer/désactiver le support SSL &lt;/li&gt;
&lt;li&gt;activer/désactiver les chiffrement des données à stocker &lt;/li&gt;
&lt;li&gt;choisir l&#39;algorithme de chiffrement &lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;J&#39;ai créé une classe qui offre toutes ces fonctionnalités. &lt;a href=&quot;http://dl.huguet.eu/bigornot/CookieManager.tar.gz&quot;&gt;Vous pouvez la télécharger ici&lt;/a&gt;. &lt;/p&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Utilisation :&lt;/span&gt; &lt;p style=&quot;font-weight: bold;&quot;&gt;Initialisation&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;include(&#39;BigOrNot_CookieManager.php&#39;);

$secretKey = &#39;Cei4Wai4ohcoo3daeHooFiek5Nah3Eet&#39;;
$manager = new BigOrNot_CookieManager($secretKey);
&lt;/pre&gt;&lt;p&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Tout ce que vous avez à faire, c&#39;est fournir une clé secrète en premier paramètre.&lt;/span&gt; &lt;span style=&quot;font-weight: normal;&quot;&gt;Si vous n&#39;êtes pas inspiré, pour générer la clé vous pouvez utiliser cette commande :&lt;/span&gt;   &lt;/p&gt;&lt;div style=&quot;padding: 10px; background: rgb(0, 0, 0) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: rgb(255, 255, 255);&quot;&gt;pwgen -sy 65 &lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;La configuration par défaut est :  &lt;/p&gt;&lt;ul&gt;&lt;li style=&quot;font-weight: normal;&quot;&gt;Chiffrement des données : activé  &lt;span style=&quot;font-size:85%;&quot;&gt;option name : &lt;span style=&quot;font-weight: bold;&quot;&gt;high_confidentiality&lt;/span&gt; (bool)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Algorithme de chiffrement : MCRYPT_RIJNDAEL_256 (Rijndael 256)&lt;/span&gt;  &lt;span style=&quot;font-size:85%;&quot;&gt;option name : &lt;span style=&quot;font-weight: bold;&quot;&gt;mcrypt_algorithm&lt;/span&gt; (&lt;a href=&quot;http://www.php.net/manual/en/mcrypt.ciphers.php&quot;&gt;voir la doc mcrypt&lt;/a&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation&quot;&gt;Mode de chiffrement par bloc&lt;/a&gt; : MCRYPT_MODE_CBC (CBC)&lt;/span&gt;  &lt;span style=&quot;font-size:85%;&quot;&gt;option name : &lt;/span&gt;&lt;span style=&quot;font-weight: bold;font-size:85%;&quot; &gt;mcrypt_mode&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt; (&lt;a href=&quot;http://www.php.net/manual/en/mcrypt.constants.php&quot;&gt;voir la doc mcrypt&lt;/a&gt;)&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Utilisation de l&#39;identifiant de session SSL : disabled  &lt;span style=&quot;font-size:85%;&quot;&gt;option name : &lt;span style=&quot;font-weight: bold;&quot;&gt;enable_ssl&lt;/span&gt; (bool)&lt;/span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Si vous souhaitez modifier la configuration, vous pouvez passer en second paramètre du constructeur un tableau d&#39;options. Par exemple, si vous souhaitez désactiver le chiffrement des données, vous pouvez faire cela&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt; :&lt;/span&gt; &lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;include(&#39;BigOrNot_CookieManager.php&#39;);

$secretKey = &#39;Cei4Wai4ohcoo3daeHooFiek5Nah3Eet&#39;;
$config = array(&#39;high_confidentiality&#39; =&gt; false);
$manager = new BigOrNot_CookieManager($secretKey, $config);
&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;font-weight: bold;&quot;&gt;Envoyer un cookie sécurisé &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;$expire = time() + 86400;
$value = $manager-&gt;setCookie(&#39;cookieName&#39;, &#39;value&#39;, &#39;username&#39;);
&lt;/pre&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Regardez le code source si vous souhaitez plus de détails sur les arguments qu&#39;il est possible d&#39;envoyer en paramètre (globalement, vous pouvez envoyer tous les paramètres que &lt;a href=&quot;http://www.php.net/setcookie&quot;&gt;setcookie()&lt;/a&gt; supporte).&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&lt;/span&gt;   &lt;p style=&quot;font-weight: bold;&quot;&gt;Lire/vérifier la valeur d&#39;un cookie&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;$value = $manager-&gt;getCookieValue(&#39;cookieName&#39;);
&lt;/pre&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Si le cookie est invalide (utilisation malicieuse, date d&#39;expiration passée), il est supprimé automatiquement. Si vous n&#39;aimez pas ce comportement, vous pouvez le desactiver en envoyant &quot;false&quot; en 2ème paramètre.&lt;/span&gt; &lt;p&gt;&lt;/p&gt;&lt;p style=&quot;font-weight: bold;&quot;&gt;Supprimer un cookie&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;$manager-&gt;deleteCookie(&#39;cookieName&#39;);
&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt; N&#39;hésitez pas à regarder le code source pour plus d&#39;infos, il est commenté. Si vous avez des questions, des remarques, des rapports de bugs, n&#39;hésitez pas à poster un commentaire :) &lt;/p&gt;&lt;p&gt;&lt;u&gt;Note:&lt;/u&gt; Il existe une classe qui permet de faire à peu près la même chose avec Django (Python) &lt;a href=&quot;http://arthurkoziel.com/2008/05/15/secure-authentication-cookies-with-django/&quot;&gt;ici&lt;/a&gt;.  Cependant elle ne gère ni le chiffrement ni SSL. &lt;/p&gt;&lt;p&gt;&lt;u&gt;Note2:&lt;/u&gt; La fonctionnalité SSL ne devrait marcher qu&#39;avec le mod_ssl d&#39;Apache (qui créé généreusement une variable d&#39;environnement SSL_SESSION_ID). &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigornot-fr.blogspot.com/feeds/604258152690233464/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3073819899020661481/604258152690233464' title='7 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/604258152690233464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/604258152690233464'/><link rel='alternate' type='text/html' href='http://bigornot-fr.blogspot.com/2008/06/scurisation-des-cookies-une.html' title='Sécurisation des cookies : une implementation en PHP'/><author><name>Mat</name><uri>http://www.blogger.com/profile/15945738194810734875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3073819899020661481.post-1517522235906374231</id><published>2008-06-13T14:22:00.000+02:00</published><updated>2008-06-13T15:09:35.812+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cookies"/><category scheme="http://www.blogger.com/atom/ns#" term="sécurité"/><title type='text'>Introduction à la sécurité des cookies</title><content type='html'>J&#39;ai vu beaucoup de gens tenter de créer un protocole de sécurisation des cookies. Nombre d&#39;entre eux sont peu fiables car leur sécurité est basée sur le secret de l&#39;algorithme employé. Ca peut marcher un certain temps, ça peut rassurer psychologiquement, mais au final, c&#39;est pas fiable.

Dans un premier temps, pour que ce soit clair, on va définir ce qu&#39;est un cookie &quot;sécurisé&quot; :
&lt;ol&gt;&lt;li&gt;Pour certains, c&#39;est un moyen de garantir l&#39;&lt;span style=&quot;font-weight: bold;&quot;&gt;authenticité&lt;/span&gt; et l&#39;&lt;span style=&quot;font-weight: bold;&quot;&gt;intégrité&lt;/span&gt; des données qui sont stockées dans un cookie. Ils ne veulent pas qu&#39;un utilisateur malicieux puisse modifier la valeur du cookie pour les duper.

&lt;/li&gt;&lt;li&gt;Pour d&#39;autres, un cookie sécurisé garantit la &lt;span style=&quot;font-weight: bold;&quot;&gt;confidentialité&lt;/span&gt; des données stockées sur la machine du client. C&#39;est à dire que les données ne peuvent être lues/comprises ni par l&#39;utilisateur, ni par une personne malicieuse qui aurait volé un coookie. Seule l&#39;application web (donc coté serveur) à le droit de lire les valeurs stockées dans le cookie.

&lt;/li&gt;&lt;li&gt;Pour d&#39;autres, un cookie sécurisé garantit qu&#39;il ne peut être ni intercepté, ni &quot;rejoué&quot; (&lt;a href=&quot;http://en.wikipedia.org/wiki/Replay_attack&quot;&gt;replay attack&lt;/a&gt;) par une personne malicieuse (dans un environnement non sécurisé : machine passeoire, cybercafé, wifi ouvert ou mal sécurisé...etc)
&lt;/li&gt;&lt;/ol&gt;
Vous allez peut être me demander : &lt;span style=&quot;font-style: italic;&quot;&gt;&quot;Mais pourquoi stocker des données sensibles/confidentielles dans des cookies ? Un peu après l&#39;age de la préhistoire on a inventé un mécanisme de sessions pour stocker ce genre de données ! Les cookies, c&#39;est aussi fiable que le réseau Wifi de ma grand mère ! Et elle n&#39;a jamais entendu parler de WPA ou de wardriving de toute sa vie ! T&#39;aimes vraiment jouer avec le feu ?&quot;&lt;/span&gt;

&lt;div style=&quot;text-align: justify;&quot;&gt;Ca fait beaucoup de questions, mais je vais tenter d&#39;y répondre.
Pour commencer, oui &lt;a href=&quot;http://redrum8.deviantart.com/art/Flower-37129006&quot;&gt;j&#39;aime jouer avec le feu !
&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Ensuite, pour cette histoire de cookies, oui il est possible de stocker des données sensibles en session sur le serveur. Mais je n&#39;aime pas les sessions (et&lt;span style=&quot;text-decoration: underline;&quot;&gt;  &lt;/span&gt;&lt;a href=&quot;http://davidvancouvering.blogspot.com/2007/09/session-state-is-evil.html&quot;&gt;je ne suis pas le seul&lt;/a&gt;) : c&#39;est une vraie galère à gérer dans un environnement multiserveur. Cela dit, on est pas là pour parler de sessions.&lt;/p&gt;

&lt;p&gt;Quoi qu&#39;il arrive, même avec une session, vous aurez à stocker l&#39;identifiant de session dans un cookie. Et ce cookie est &lt;a href=&quot;http://phpsec.org/projects/guide/fr/4.html&quot;&gt;TRES IMPORTANT&lt;/a&gt;... il doit être sécurisé :) La plupart des applications sont concernées par la sécurité des coookies.&lt;/p&gt;

&lt;p&gt;Donc poursuivons : suivant la nature des données que vous aurez à stocker dans des cookies, vous allez devoir considérer les différents points évoqués plus haut (authenticité, integrité, confidentialité, &quot;replay attack&quot; et interception de cookie) et choisir ceux que vous voudrez prendre en compte dans votre politique de sécurité.&lt;/p&gt;

&lt;div style=&quot;text-align: justify;&quot;&gt;Pour chacun des problèmes évoqués, il existe une solution (cryptographique) :
&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Le problème d&#39;&lt;span style=&quot;font-weight: bold;&quot;&gt;intégrité&lt;/span&gt; et d&#39;&lt;span style=&quot;font-weight: bold;&quot;&gt;authenticité&lt;/span&gt; peut être résolu avec des fonctions de &lt;a href=&quot;http://fr.wikipedia.org/wiki/Hashage&quot;&gt;hachage&lt;/a&gt;. Nous allons utiliser une solution basée sur ces fonctions de hachage : &lt;a href=&quot;http://fr.wikipedia.org/wiki/HMAC&quot;&gt;HMAC&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Le problème de &lt;span style=&quot;font-weight: bold;&quot;&gt;confidentialité&lt;/span&gt; peut être résolu en utilisant des fonctions de &lt;a href=&quot;http://fr.wikipedia.org/wiki/Chiffrement_par_bloc&quot;&gt;chiffrement par bloc&lt;/a&gt; (par exemple &lt;a href=&quot;http://fr.wikipedia.org/wiki/Standard_de_chiffrement_avanc%C3%A9&quot;&gt;AES&lt;/a&gt;).

&lt;/li&gt;&lt;li&gt;Le problème de &lt;span style=&quot;font-weight: bold;&quot;&gt;&quot;replay attack&quot;&lt;/span&gt; peut être résolu en combinant l&#39;utilisation d&#39;une fonction HMAC et en utilisant le protocole de transport sécurisé &lt;a href=&quot;http://fr.wikipedia.org/wiki/SSL&quot;&gt;SSL/TLS&lt;/a&gt;.

&lt;/li&gt;&lt;li&gt;Le risque d&#39;&lt;span style=&quot;font-weight: bold;&quot;&gt;interception&lt;/span&gt; de cookies peut être réduit en utilisant SSL. (réduit seulement : un cookie peut toujours être volé d&#39;une autre façon car il est stocké de sur la machine du client, il peut donc être volé).
Cependant, l&#39;interception d&#39;un cookie sécurisé ne devient plus très interressante si la valeur est chiffrée, non rejouable dans une &quot;replay attack&quot; et pas modifiable à cause des contrôles d&#39;intégrité.
Cela devient relativement inutile d&#39;intercepter ce genre de cookies.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Bref, si vous avez tout suivi jusqu&#39;ici, vous devriez être interressé par une solution concrête pour sécuriser des cookies, avec plein de détails croustillants ! Je vous invite donc à lire &lt;a href=&quot;http://www.cse.msu.edu/%7Ealexliu/publications/Cookie/cookie.pdf&quot;&gt;ce papier : &quot;A Secure Cookie Protocol&quot;&lt;/a&gt; écrit par &lt;strong&gt;&lt;span style=&quot;font-weight: normal;font-size:100%;&quot; &gt;Alex X. Liu.&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
Dans le prochain article, nous verrons comment implémenter ce protocole en PHP. Et peut être plus tard comment l&#39;intégrer au Zend Framework.&lt;/p&gt;

&lt;p&gt;Les commentaires sont les bienvenus :)&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigornot-fr.blogspot.com/feeds/1517522235906374231/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3073819899020661481/1517522235906374231' title='2 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/1517522235906374231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/1517522235906374231'/><link rel='alternate' type='text/html' href='http://bigornot-fr.blogspot.com/2008/06/introduction-la-scurit-des-cookies.html' title='Introduction à la sécurité des cookies'/><author><name>Mat</name><uri>http://www.blogger.com/profile/15945738194810734875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3073819899020661481.post-1813228987640108154</id><published>2008-06-13T14:13:00.000+02:00</published><updated>2008-06-13T14:22:01.513+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="presentation"/><title type='text'>Encore un blog !</title><content type='html'>Salut

&lt;p&gt;
Voici une version française de mon blog : &lt;a href=&quot;http://bigornot.blogspot.com&quot;&gt;http://bigornot.blogspot.com&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Vous pourrez y trouver des articles sur le Developpement Web (PHP en particulier), la sécurité, linux, la &quot;scalability&quot;, les bonnes pratiques du calibrage de bigorneaux, et tout ce qui me passe par la tête.
&lt;/p&gt;

&lt;p&gt;J&#39;espère que ça pourra être utile à quelqu&#39;un :)&lt;/p&gt;

&lt;p&gt;
Bonne lecture&lt;br /&gt;
Mat
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigornot-fr.blogspot.com/feeds/1813228987640108154/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3073819899020661481/1813228987640108154' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/1813228987640108154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3073819899020661481/posts/default/1813228987640108154'/><link rel='alternate' type='text/html' href='http://bigornot-fr.blogspot.com/2008/06/encore-un-blog.html' title='Encore un blog !'/><author><name>Mat</name><uri>http://www.blogger.com/profile/15945738194810734875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>