{"id":230298,"date":"2022-12-09T11:17:00","date_gmt":"2022-12-09T08:17:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230298"},"modified":"2022-12-07T11:58:51","modified_gmt":"2022-12-07T08:58:51","slug":"bezpieczne-przesylanie-formularzy-wordpress","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pl\/bezpieczne-przesylanie-formularzy-wordpress\/","title":{"rendered":"Bezpieczne przesy\u0142anie formularzy WordPress"},"content":{"rendered":"\n<p>Lata temu napisa\u0142em post, w kt\u00f3rym udost\u0119pni\u0142em funkcj\u0119 publiczn\u0105, aby ustali\u0107, czy u\u017cytkownik ma uprawnienia do zapisywania informacji w bazie danych WordPressa. Orygina\u0142 w ca\u0142ej okaza\u0142o\u015bci (wraz z solidnymi komentarzami) mo\u017cecie zobaczy\u0107 <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/4468321\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tutaj<\/a><\/strong> (ma nawet pi\u0119\u0107 lat \u2013 wow).<\/p>\n<p>Jak w przypadku wszystkiego, co jest zwi\u0105zane z programowaniem, czas p\u0142ynie, rzeczy s\u0105 udoskonalane i [miejmy nadziej\u0119] staj\u0105 si\u0119 lepsze ni\u017c wcze\u015bniej.<\/p>\n<p>Chocia\u017c nadal u\u017cywam i polecam wariant funkcji <strong>user_can_save<\/strong> (lub <strong>userCanSave<\/strong> ), uwa\u017cam r\u00f3wnie\u017c, \u017ce wa\u017cne jest, aby przej\u015b\u0107 przez proces wyodr\u0119bniania procesu weryfikacji \u017c\u0105dania.<\/p>\n<p>Wi\u0119c teraz nie chodzi tylko o ustalenie, czy u\u017cytkownik ma uprawnienia, ale o weryfikacj\u0119 informacji o zabezpieczeniach pochodz\u0105cych od klienta \u2013 czy to za po\u015brednictwem poczty z powrotem do serwera, czy \u017c\u0105dania wys\u0142anego przez Ajax \u2013 i zrobienie tego przy u\u017cyciu dobrych technik programowania, kt\u00f3re s\u0105 zgodne zar\u00f3wno z WordPress, jak i z PHP.<\/p>\n<p>Aby by\u0142o jasne, chodzi bardziej o bezpieczne przesy\u0142anie formularzy WordPress ze strony opcji lub strony ustawie\u0144 ni\u017c, powiedzmy, formularz pochodz\u0105cy z szablonu. To kolejny post na inny czas.<\/p>\n<p>Ale wci\u0105\u017c jest wielu z nas pracuj\u0105cych nad tworzeniem aplikacji na WordPressie, kt\u00f3re wymagaj\u0105 nast\u0119puj\u0105cych rzeczy.<\/p>\n<h2>Bezpieczne przesy\u0142anie formularzy WordPress<\/h2>\n<p>W tym po\u015bcie nie zamierzam przejmowa\u0107 si\u0119 szczeg\u00f3\u0142ami okre\u015blania, czy co\u015b jest <strong><a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/wp_is_post_autosave\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">autozapisem<\/a><\/strong>, czy <strong><a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/wp_is_post_revision\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wersj\u0105 postu.<\/a><\/strong><\/p>\n<\/p>\n<p>Jednak zamierzam przej\u015b\u0107 przez proces przejmowania funkcji odpowiedzialnej za walidacj\u0119 przychodz\u0105cych informacji i robienia tego przy u\u017cyciu nowoczesnego podej\u015bcia z wykorzystaniem praktyk zorientowanych obiektowo oraz zar\u00f3wno API WordPressa, jak i funkcji PHP.<\/p>\n<h3>1 Zaczynaj\u0105c od poziomu og\u00f3lnego<\/h3>\n<p>Z poziomu podstawowego za\u0142\u00f3\u017cmy, \u017ce istnieje klasa bazowa, z kt\u00f3rej istniej\u0105 inne podklasy wykorzystuj\u0105ce t\u0119 funkcj\u0119. To m\u00f3wi nam, \u017ce musimy u\u017cy\u0107 chronionego modyfikatora widoczno\u015bci.<\/p>\n<p>Wiemy r\u00f3wnie\u017c, \u017ce b\u0119dziemy mieli do czynienia z warto\u015bci\u0105 WordPress nonce i powi\u0105zan\u0105 akcj\u0105. Oznacza to, \u017ce <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-00-function-signature-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">podpis funkcji b\u0119dzie wygl\u0105da\u0142 mniej wi\u0119cej tak<\/a><\/strong> :<\/p>\n<pre><code>&lt;?php\nprotected function verifyRequest($nonce, $action);<\/code><\/pre>\n<h3>2 Oczy\u015b\u0107 dane, zweryfikuj nico\u015b\u0107<\/h3>\n<p>Jak na wszystko, co jest wysy\u0142ane na serwer, wiemy, \u017ce b\u0119dziemy musieli zweryfikowa\u0107, czy dane s\u0105 ustawione, a je\u015bli tak, b\u0119dziemy musieli oczy\u015bci\u0107 informacje.<\/p>\n<p>Oznacza to, \u017ce b\u0119dziemy potrzebowa\u0107 nast\u0119puj\u0105cych funkcji:<\/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\">paski uko\u015bne<\/a><\/strong><\/li>\n<\/ul>\n<p>Wiemy te\u017c, \u017ce b\u0119dziemy musieli zweryfikowa\u0107 warto\u015b\u0107 jednorazow\u0105, wi\u0119c b\u0119dziemy te\u017c potrzebowa\u0107 <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 Pierwsze przej\u015bcie do pracy<\/h3>\n<p>Dzia\u0142aj\u0105cy pierwszy przebieg tej funkcji mo\u017ce wygl\u0105da\u0107 mniej wi\u0119cej <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-00-verify-request-1-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tak:<\/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>Ale co, je\u015bli kto\u015b udost\u0119pnia dane, kt\u00f3re wys\u0142a\u0142y \u017c\u0105danie <strong>POST<\/strong> (w przeciwie\u0144stwie do \u017c\u0105dania <strong>GET<\/strong> )? Nast\u0119pnie mo\u017cemy zmodyfikowa\u0107 funkcj\u0119 tak, aby wygl\u0105da\u0142a mniej wi\u0119cej <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-02-verify-request-2-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tak:<\/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>I to by wystarczy\u0142o. Ale je\u015bli naprawd\u0119 chcemy, aby dana funkcja by\u0142a tak czysta, jak to tylko mo\u017cliwe, mogliby\u015bmy to rozbi\u0107 jeszcze bardziej.<\/p>\n<h3>4 Funkcja do ka\u017cdego celu<\/h3>\n<p>Bior\u0105c pod uwag\u0119 powy\u017cszy kod, wiemy, \u017ce musimy obs\u0142ugiwa\u0107 zar\u00f3wno \u017c\u0105dania GET, jak i \u017c\u0105dania POST. PHP oferuje funkcj\u0119 <strong>filter_input<\/strong>, kt\u00f3ra jest pomocna, \u0142atwiejsza do odczytania (c\u00f3\u017c, jest to subiektywne), ale tak\u017ce przechodzi kilka kontroli jako\u015bci kodu.<\/p>\n<p>Co wi\u0119cej, mo\u017cemy u\u017cy\u0107 <strong><a href=\"https:\/\/en.wikipedia.org\/wiki\/Factory_method_pattern\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">prostej funkcji fabrycznej,<\/a><\/strong> aby podzieli\u0107 logik\u0119 na oddzielne funkcje, takie jak ta:<\/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=\"Bezpieczne przesy\u0142anie formularzy WordPress\" ><\/a><\/p>\n<p>Najpierw musimy napisa\u0107 dwie oddzielne funkcje \u2013 jedn\u0105 <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-03-verify-post-request-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">dla \u017c\u0105dania POST:<\/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>I jeden <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-04-verify-get-request-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">na \u017c\u0105danie GET:<\/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>Nast\u0119pnie mo\u017cemy po\u0142\u0105czy\u0107 to w <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/b1eac5df600177b7beb423477ccceee6#file-05-verify-request-factory-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">oryginaln\u0105 funkcj\u0119 w ten spos\u00f3b:<\/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>Czyste zarz\u0105dzanie przychodz\u0105cymi \u017c\u0105daniami<\/h2>\n<p>By\u0107 mo\u017ce wygl\u0105da to na skomplikowany spos\u00f3b obs\u0142ugi prostego rozwi\u0105zania, bior\u0105c pod uwag\u0119 pocz\u0105tkowy zestaw kodu, kt\u00f3ry zosta\u0142 udost\u0119pniony.<\/p>\n<p>Jest to z pewno\u015bci\u0105 mo\u017cliwe, zw\u0142aszcza je\u015bli jeste\u015b pod presj\u0105 czasu lub nie zale\u017cy ci tak bardzo na dzieleniu rzeczy na najmniejsze mo\u017cliwe atomowe (lub nawet testowalne) komponenty.<\/p>\n<p>Ale je\u015bli chcesz pisa\u0107 kod obiektowy z najwy\u017csz\u0105 precyzj\u0105, by\u0107 mo\u017ce ten proces w\u0142a\u015bnie w tym pomo\u017ce.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">\u0179r\u00f3d\u0142o nagrywania:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bardziej chodzi o bezpieczne przesy\u0142anie formularzy WordPress ze strony opcji lub strony ustawie\u0144 ni\u017c w przypadku formularza pochodz\u0105cego z szablonu.<\/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":[897,805,845,866],"tags":[1169],"class_list":["post-230298","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kod","category-php-7","category-samouczki","category-wordpress-7","tag-affiai-pl"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230298","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/comments?post=230298"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230298\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media\/236238"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media?parent=230298"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/categories?post=230298"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/tags?post=230298"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}