{"id":230823,"date":"2022-12-09T11:29:00","date_gmt":"2022-12-09T08:29:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230823"},"modified":"2022-12-07T11:58:49","modified_gmt":"2022-12-07T08:58:49","slug":"soumission-securisee-du-formulaire-wordpress","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/fr\/soumission-securisee-du-formulaire-wordpress\/","title":{"rendered":"Soumission s\u00e9curis\u00e9e du formulaire WordPress"},"content":{"rendered":"\n<p>Il y a des ann\u00e9es, j&rsquo;ai \u00e9crit un article dans lequel je partageais une fonction publique pour d\u00e9terminer si l&rsquo;utilisateur \u00e9tait autoris\u00e9 \u00e0 enregistrer des informations dans la base de donn\u00e9es WordPress. Vous pouvez voir l&rsquo;essentiel original dans toute sa splendeur (avec les commentaires solides) <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/4468321\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">ici<\/a><\/strong> (il a cinq ans, m\u00eame &#8211; wow).<\/p>\n<p>Comme pour tout ce qui concerne la programmation, le temps passe, les choses s&rsquo;affinent et les choses [esp\u00e9rons-le] s&rsquo;am\u00e9liorent par rapport \u00e0 avant.<\/p>\n<p>Bien que j&rsquo;utilise et recommande toujours une variante de la <strong>fonction user_can_save<\/strong> (ou <strong>userCanSave<\/strong> ), je pense \u00e9galement qu&rsquo;il est important de passer par le processus de s\u00e9paration du processus de v\u00e9rification de la demande.<\/p>\n<p>Alors maintenant, il ne s&rsquo;agit pas seulement de d\u00e9terminer si l&rsquo;utilisateur a des autorisations, mais il s&rsquo;agit de v\u00e9rifier les informations de s\u00e9curit\u00e9 provenant du client &#8211; que ce soit via une publication vers le serveur ou une demande faite via Ajax &#8211; et de le faire en utilisant de bonnes techniques de programmation qui s&rsquo;alignent \u00e0 la fois avec WordPress et avec PHP.<\/p>\n<p>Pour \u00eatre clair, il s&rsquo;agit plus d&rsquo;une soumission de formulaire WordPress s\u00e9curis\u00e9e \u00e0 partir d&rsquo;une page d&rsquo;options ou d&rsquo;une page de param\u00e8tres que d&rsquo;un formulaire provenant d&rsquo;un mod\u00e8le. C&rsquo;est un autre post pour une autre fois.<\/p>\n<p>Mais encore, nous sommes nombreux \u00e0 travailler sur la cr\u00e9ation d&rsquo;applications sur WordPress et qui n\u00e9cessitent ce qui suit.<\/p>\n<h2>Soumission s\u00e9curis\u00e9e du formulaire WordPress<\/h2>\n<p>Dans cet article, je ne vais pas me pr\u00e9occuper de passer en revue les d\u00e9tails pour d\u00e9terminer si quelque chose est une <strong><a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/wp_is_post_autosave\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">sauvegarde automatique<\/a><\/strong> ou une <strong><a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/wp_is_post_revision\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">r\u00e9vision de publication.<\/a><\/strong><\/p>\n<\/p>\n<p>Cependant, je vais parcourir le processus de prise en charge d&rsquo;une fonction charg\u00e9e de valider les informations entrantes et de le faire en utilisant une approche moderne utilisant des pratiques orient\u00e9es objet et \u00e0 la fois des API WordPress et des fonctions PHP.<\/p>\n<h3>1 Commencer \u00e0 un niveau g\u00e9n\u00e9rique<\/h3>\n<p>Du niveau fondamental, supposons qu&rsquo;il existe une classe de base \u00e0 partir de laquelle il existe d&rsquo;autres sous-classes qui exploitent cette fonction. Cela nous indique que nous devons utiliser le modificateur de visibilit\u00e9 prot\u00e9g\u00e9.<\/p>\n<p>Nous savons \u00e9galement que nous allons avoir affaire \u00e0 une valeur WordPress nonce et \u00e0 une action associ\u00e9e. Cela signifie que la <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-00-function-signature-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">signature de la fonction ressemblera \u00e0 ceci<\/a><\/strong>\u00a0:<\/p>\n<pre><code>&lt;?php\nprotected function verifyRequest($nonce, $action);<\/code><\/pre>\n<h3>2 D\u00e9sinfectez les donn\u00e9es, v\u00e9rifiez le nonce<\/h3>\n<p>Comme pour tout ce qui est publi\u00e9 sur le serveur, nous savons que nous allons devoir v\u00e9rifier que les donn\u00e9es sont d\u00e9finies et si c&rsquo;est le cas, nous allons devoir nettoyer les informations.<\/p>\n<p>Cela signifie que nous allons avoir besoin des fonctions suivantes\u00a0:<\/p>\n<ul>\n<li><a href=\"https:\/\/php.net\/manual\/en\/function.isset.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">isset<\/a><\/li>\n<li><a href=\"https:\/\/php.net\/manual\/en\/function.strip-tags.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">strip_tags<\/a><\/li>\n<li><strong><a href=\"https:\/\/php.net\/manual\/en\/function.stripslashes.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">bandes de coups de fouet<\/a><\/strong><\/li>\n<\/ul>\n<p>Et nous savons aussi que nous allons devoir v\u00e9rifier le nonce, donc nous allons aussi avoir besoin de <strong><a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/wp_verify_nonce\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_verify_nonce<\/a><\/strong>.<\/p>\n<h3>3 Un premier passage fonctionnel<\/h3>\n<p>Une premi\u00e8re passe de travail de cette fonction peut ressembler <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-00-verify-request-1-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">\u00e0 ceci\u00a0:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\nprotected function verifyRequest($nonce, $action)\n{\n    return isset($_GET[$nonce]) &amp;&amp;\n           wp_verify_nonce(strip_tags(stripslashes($_GET[$nonce])), $action);\n}\n<\/code><\/pre>\n<p>Mais que se passe-t-il si quelqu&rsquo;un partage des donn\u00e9es qui ont envoy\u00e9 une requ\u00eate <strong>POST<\/strong> (par opposition \u00e0 une requ\u00eate <strong>GET<\/strong> )\u00a0? Ensuite, nous pourrions modifier la fonction pour qu&rsquo;elle ressemble <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-02-verify-request-2-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">\u00e0 ceci\u00a0:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\nprotected function verifyRequest($nonce, $action)\n{\n    return (isset($_GET[$nonce]) &amp;&amp;\n            wp_verify_nonce(strip_tags(stripslashes($_GET[$nonce])), $action)) || (isset($_POST[$nonce]) &amp;&amp;\n            wp_verify_nonce(strip_tags(stripslashes($_POST[$nonce])), $action)\n        );\n}\n<\/code><\/pre>\n<p>Et ce serait suffisant. Mais si nous voulons vraiment qu&rsquo;une fonction donn\u00e9e soit aussi pure que possible, alors nous pourrions la d\u00e9composer encore plus.<\/p>\n<h3>4 Une fonction pour chaque usage<\/h3>\n<p>Compte tenu du code ci-dessus, nous savons que nous devons g\u00e9rer \u00e0 la fois les requ\u00eates GET et les requ\u00eates POST. PHP propose une fonction <strong>filter_input<\/strong> qui est utile, plus facile \u00e0 lire (enfin, c&rsquo;est subjectif), mais passe \u00e9galement plusieurs inspections de qualit\u00e9 du code.<\/p>\n<p>De plus, nous pouvons utiliser une <strong><a href=\"https:\/\/en.wikipedia.org\/wiki\/Factory_method_pattern\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">simple<\/a><\/strong> fonction d&rsquo;usine pour s\u00e9parer la logique en plusieurs fonctions comme celle-ci\u00a0:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-162230-61e73927a6ca8.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-162230-61e73927a6ca8.png\" alt=\"Soumission s\u00e9curis\u00e9e du formulaire WordPress\" ><\/a><\/p>\n<p>Tout d&rsquo;abord, nous devons \u00e9crire deux fonctions distinctes &#8211; une <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-03-verify-post-request-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">pour une requ\u00eate POST\u00a0:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\nprivate function verifyPostRequest($nonce, $action)\n{\n    return\n        isset($_POST[$nonce]) &amp;&amp;\n        wp_verify_nonce(strip_tags(stripslashes(filter_input(INPUT_POST, $nonce))), $action);\n}<\/code><\/pre>\n<p>Et un <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-04-verify-get-request-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">pour une requ\u00eate GET\u00a0:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\nprivate function verifyGetRequest($nonce, $action)\n{\n    return\n        isset($_GET[$nonce]) &amp;&amp;\n        wp_verify_nonce(strip_tags(stripslashes(filter_input(INPUT_GET, $nonce))), $action);\n}<\/code><\/pre>\n<p>Ensuite, nous pouvons le lier ensemble dans <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-05-verify-request-factory-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">la fonction d&rsquo;origine comme ceci\u00a0:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\nprotected function verifyRequest($nonce, $action)\n{\n    switch (strtolower($_SERVER['REQUEST_METHOD'])) {\n        case 'post':\n            return $this-&gt;verifyPostRequest($nonce, $action);\n            break;\n        case 'get':\n            return $this-&gt;verifyGetRequest($nonce, $action);\n            break;\n        default:\n            return false;\n            break;\n    }\n}<\/code><\/pre>\n<h2>G\u00e9rer proprement les demandes entrantes<\/h2>\n<p>Cela ressemble peut-\u00eatre \u00e0 une mani\u00e8re compliqu\u00e9e de g\u00e9rer une solution simple compte tenu de l&rsquo;ensemble initial de code partag\u00e9.<\/p>\n<p>C&rsquo;est certainement possible, surtout si vous \u00eates soumis \u00e0 des contraintes de temps ou si vous ne vous souciez pas autant de diviser les choses en composants atomiques (ou m\u00eame testables) les plus petits possibles.<\/p>\n<p>Mais si vous cherchez \u00e0 \u00e9crire du code orient\u00e9 objet avec le plus haut degr\u00e9 de pr\u00e9cision, peut-\u00eatre que ce processus vous aidera exactement \u00e0 cela.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Source d&rsquo;enregistrement:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Il s&rsquo;agit plus d&rsquo;une soumission de formulaire WordPress s\u00e9curis\u00e9e \u00e0 partir d&rsquo;une page d&rsquo;options ou d&rsquo;une page de param\u00e8tres que d&rsquo;un formulaire provenant d&rsquo;un mod\u00e8le.<\/p>\n","protected":false},"author":1,"featured_media":236238,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[893,801,841,862],"tags":[1167],"class_list":["post-230823","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-code-2","category-php-3","category-tutoriels","category-wordpress-3","tag-affiai-fr"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/230823","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/comments?post=230823"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/230823\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media\/236238"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media?parent=230823"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/categories?post=230823"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/tags?post=230823"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}