{"id":1723,"date":"2021-05-17T08:53:56","date_gmt":"2021-05-17T08:53:56","guid":{"rendered":"https:\/\/phptutorial.net\/?page_id=1723"},"modified":"2025-04-07T14:57:13","modified_gmt":"2025-04-07T14:57:13","slug":"php-csrf","status":"publish","type":"page","link":"https:\/\/www.phptutorial.net\/php-tutorial\/php-csrf\/","title":{"rendered":"PHP CSRF"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you will learn about cross-site request forgery (CSRF) attacks and how to prevent them in PHP.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='what-is-csrf'>What is CSRF <a href=\"#what-is-csrf\" class=\"anchor\" id=\"what-is-csrf\" title=\"Anchor for What is CSRF\">#<\/a><\/h2>\n\n\n\n<p>CSRF stands for cross-site request forgery. It&#8217;s a kind of attack in which a hacker forces you to execute an action against a website where you&#8217;re currently logged in.<\/p>\n\n\n\n<p>For example, you visit the <code>malicious-site.com<\/code> that has a hidden form. And that form submits on page load to <code>yourbank.com\/transfer-fund<\/code> form.<\/p>\n\n\n\n<p>Because you&#8217;re currently logged in to the <code>yourbank.com<\/code>, the request silently transfers a fund out of your bank account.<\/p>\n\n\n\n<p>If <code>yourbank.com\/transfer-fund<\/code> implements the CSRF correctly, it generates a one-time token and inserts the token into the fund transfer form like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;input type=<span class=\"hljs-string\">\"hidden\"<\/span> \n       name=<span class=\"hljs-string\">\"token\"<\/span>\n       value=<span class=\"hljs-string\">\"b3f44c1eb885409c222fdb78c125f5e7050ce4f3d15e8b15ffe51678dd3a33d3a18dd3\"<\/span>&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>When the <code>malicious-site.com<\/code> submits the form, the <code>yourbank.com\/transfer-fund<\/code> form compares the token with the one on the <code>yourbank.com<\/code>&#8216;s server.<\/p>\n\n\n\n<p>If the token doesn&#8217;t exist in the submitted data or it doesn&#8217;t match with the token on the server, the fund transfer form will reject the submission and return an error.<\/p>\n\n\n\n<p>When the <code>malicious-site.com<\/code> tries to submit the form, the token is likely not available or won&#8217;t match.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='how-to-implement-csrf-token-in-php'>How to implement CSRF token in PHP <a href=\"#how-to-implement-csrf-token-in-php\" class=\"anchor\" id=\"how-to-implement-csrf-token-in-php\" title=\"Anchor for How to implement CSRF token in PHP\">#<\/a><\/h2>\n\n\n\n<p>First, create a one-time token and add it to the <code>$_SESSION<\/code> variable:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$_SESSION&#91;<span class=\"hljs-string\">'token'<\/span>] = md5(uniqid(mt_rand(), <span class=\"hljs-keyword\">true<\/span>));<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, add a hidden field whose value is the token and insert it into the form:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;input type=<span class=\"hljs-string\">\"hidden\"<\/span> name=<span class=\"hljs-string\">\"token\"<\/span> value=<span class=\"hljs-string\">\"&lt;?php echo $_SESSION&#91;'token'] ?? '' ?&gt;\"<\/span>&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, when the form is submitted, check if the token exists in the <code>INPUT_POST<\/code> and compare it with the <code>$_SESSION['token']<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\n\n$token = filter_input(INPUT_POST, <span class=\"hljs-string\">'token'<\/span>, FILTER_SANITIZE_STRING);\n\n<span class=\"hljs-keyword\">if<\/span> (!$token || $token !== $_SESSION&#91;<span class=\"hljs-string\">'token'<\/span>]) {\n    <span class=\"hljs-comment\">\/\/ return 405 http status code<\/span>\n    header($_SERVER&#91;<span class=\"hljs-string\">'SERVER_PROTOCOL'<\/span>] . <span class=\"hljs-string\">' 405 Method Not Allowed'<\/span>);\n    <span class=\"hljs-keyword\">exit<\/span>;\n} <span class=\"hljs-keyword\">else<\/span> {\n    <span class=\"hljs-comment\">\/\/ process the form<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If the token doesn&#8217;t exist or doesn&#8217;t match, return the 405 HTTP status code and exit.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='php-csrf-example'>PHP CSRF example <a href=\"#php-csrf-example\" class=\"anchor\" id=\"php-csrf-example\" title=\"Anchor for PHP CSRF example\">#<\/a><\/h2>\n\n\n\n<p>We&#8217;ll create a <a href=\"https:\/\/phptutorial.net\/app\/fundtransfer\/\" target=\"_blank\" rel=\"noreferrer noopener\">simple fund transfer form<\/a> to demonstrate how to prevent a CSRF attack:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"374\" height=\"362\" src=\"https:\/\/phptutorial.net\/wp-content\/uploads\/2021\/05\/php-csrf-demo.png\" alt=\"php csrf demo\" class=\"wp-image-1729\" srcset=\"https:\/\/www.phptutorial.net\/wp-content\/uploads\/2021\/05\/php-csrf-demo.png 374w, https:\/\/www.phptutorial.net\/wp-content\/uploads\/2021\/05\/php-csrf-demo-300x290.png 300w\" sizes=\"auto, (max-width: 374px) 100vw, 374px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/phptutorial.net\/wp-content\/uploads\/2021\/05\/php-csrf-demo.png\" alt=\"\" class=\"wp-image-1725\"\/><\/figure>\n\n\n\n<p>First, create the following file and directory:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">.\n\u251c\u2500\u2500 css\n\u2502   \u2514\u2500\u2500 style.css\n\u251c\u2500\u2500 inc\n\u2502   \u251c\u2500\u2500 footer.php\n\u2502   \u251c\u2500\u2500 get.php\n\u2502   \u251c\u2500\u2500 header.php\n\u2502   \u2514\u2500\u2500 post.php\n\u2514\u2500\u2500 index.php<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='header-php'>header.php <a href=\"#header-php\" class=\"anchor\" id=\"header-php\" title=\"Anchor for header.php\">#<\/a><\/h3>\n\n\n\n<p>The <code>header.php<\/code> file contains the code that shows the first section of the page:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;!DOCTYPE html&gt;\n&lt;html lang=<span class=\"hljs-string\">\"en\"<\/span>&gt;\n&lt;head&gt;\n    &lt;meta charset=<span class=\"hljs-string\">\"UTF-8\"<\/span>&gt;\n    &lt;meta name=<span class=\"hljs-string\">\"viewport\"<\/span> content=<span class=\"hljs-string\">\"width=device-width, initial-scale=1.0\"<\/span>&gt;\n    &lt;link rel=<span class=\"hljs-string\">\"stylesheet\"<\/span> href=<span class=\"hljs-string\">\"css\/style.css\"<\/span>&gt;\n    &lt;title&gt;PHP CSRF - Fund Transfer Demo&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;main&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='footer-php'>footer.php <a href=\"#footer-php\" class=\"anchor\" id=\"footer-php\" title=\"Anchor for footer.php\">#<\/a><\/h3>\n\n\n\n<p>The <code>footer.php<\/code> file contains the closing tags corresponding to the opening tags in the <code>header.php<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">     &lt;\/main&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='index-php-file'>index.php file <a href=\"#index-php-file\" class=\"anchor\" id=\"index-php-file\" title=\"Anchor for index.php file\">#<\/a><\/h3>\n\n\n\n<p>Place the following code to the <code>index.php<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\n\nsession_start();\n\n<span class=\"hljs-keyword\">require<\/span> <span class=\"hljs-keyword\">__DIR__<\/span> .  <span class=\"hljs-string\">'\/inc\/header.php'<\/span>;\n\n$errors = &#91;]; <span class=\"hljs-comment\">\/\/ for storing the error messages<\/span>\n$inputs = &#91;]; <span class=\"hljs-comment\">\/\/ for storing sanitized input values<\/span>\n\n$request_method = strtoupper($_SERVER&#91;<span class=\"hljs-string\">'REQUEST_METHOD'<\/span>]);\n\n<span class=\"hljs-keyword\">if<\/span> ($request_method === <span class=\"hljs-string\">'GET'<\/span>) {\n\t<span class=\"hljs-comment\">\/\/ generate a token<\/span>\n\t$_SESSION&#91;<span class=\"hljs-string\">'token'<\/span>] = bin2hex(random_bytes(<span class=\"hljs-number\">35<\/span>));\n\t<span class=\"hljs-comment\">\/\/ show the form<\/span>\n\t<span class=\"hljs-keyword\">require<\/span> <span class=\"hljs-keyword\">__DIR__<\/span> . <span class=\"hljs-string\">'\/inc\/get.php'<\/span>;\n} <span class=\"hljs-keyword\">elseif<\/span> ($request_method === <span class=\"hljs-string\">'POST'<\/span>) {\n\t<span class=\"hljs-comment\">\/\/ handle the form submission<\/span>\n\t<span class=\"hljs-keyword\">require<\/span> <span class=\"hljs-keyword\">__DIR__<\/span> .  <span class=\"hljs-string\">'\/inc\/post.php'<\/span>;\n\t<span class=\"hljs-comment\">\/\/ re-display the form if the form contains errors<\/span>\n\t<span class=\"hljs-keyword\">if<\/span> ($errors) {\n\t\t<span class=\"hljs-keyword\">require<\/span>\t<span class=\"hljs-keyword\">__DIR__<\/span> .  <span class=\"hljs-string\">'\/inc\/get.php'<\/span>;\n\t}\n}\n\n<span class=\"hljs-keyword\">require<\/span> <span class=\"hljs-keyword\">__DIR__<\/span> . <span class=\"hljs-string\">'\/inc\/footer.php'<\/span>;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How the <code>index.php<\/code> works.<\/p>\n\n\n\n<p>First, start a new session by calling the <code>session_start()<\/code> function; use the <code>$errors<\/code> array to store the error messages and the <code>$inputs<\/code> array is to store sanitized input values.<\/p>\n\n\n\n<p>Next, show the form in the <code>get.php<\/code> file if the HTTP request is GET. <\/p>\n\n\n\n<p>The following generates the one-time token:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$_SESSION&#91;<span class=\"hljs-string\">'token'<\/span>] = bin2hex(random_bytes(<span class=\"hljs-number\">35<\/span>));<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>random_bytes(35)<\/code> generates a random string with 35 characters. And the <code>bin2hex()<\/code> function returns the hexadecimal representation of the random string. The token will look like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">c4724e490407a1770efcc4ea19776c06e0bd4614a9dd37900f5eb001581dffee9b377a<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then, load the code from the <code>post.php<\/code> file to handle the form submission if the HTTP request is POST.<\/p>\n\n\n\n<p>After that, show the form again with error messages if the form data is invalid. Note that if the form has errors, the <code>$errors<\/code> will contain the error messages.<\/p>\n\n\n\n<p>Finally, display a message from the <code>message.php<\/code> file to inform that the fund has been transferred successfully.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='get-php'>get.php <a href=\"#get-php\" class=\"anchor\" id=\"get-php\" title=\"Anchor for get.php\">#<\/a><\/h3>\n\n\n\n<p>The following creates the fund transfer form with two input fields transfer amount and recipient account:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;form action=<span class=\"hljs-string\">\"&lt;?= htmlspecialchars($_SERVER&#91;'PHP_SELF']) ?&gt;\"<\/span> method=<span class=\"hljs-string\">\"post\"<\/span>&gt;\n    &lt;header&gt;\n        &lt;h1&gt;Fund Transfer&lt;\/h1&gt;\n    &lt;\/header&gt;\n    &lt;div&gt;\n        &lt;label <span class=\"hljs-keyword\">for<\/span>=<span class=\"hljs-string\">\"amount\"<\/span>&gt;Amount (between $<span class=\"hljs-number\">1<\/span>-$<span class=\"hljs-number\">5000<\/span>):&lt;\/label&gt;\n        &lt;input type=<span class=\"hljs-string\">\"number\"<\/span> name=<span class=\"hljs-string\">\"amount\"<\/span> value=<span class=\"hljs-string\">\"&lt;?= $inputs&#91;'amount'] ?? '' ?&gt;\"<\/span> id=<span class=\"hljs-string\">\"amount\"<\/span> placeholder=<span class=\"hljs-string\">\"Enter the transfered amount\"<\/span>&gt;\n        &lt;small&gt;<span class=\"hljs-meta\">&lt;?<\/span>= $errors&#91;<span class=\"hljs-string\">'amount'<\/span>] ?? <span class=\"hljs-string\">''<\/span> <span class=\"hljs-meta\">?&gt;<\/span>&lt;\/small&gt;\n    &lt;\/div&gt;\n\n    &lt;div&gt;\n        &lt;label <span class=\"hljs-keyword\">for<\/span>=<span class=\"hljs-string\">\"recipient_account\"<\/span>&gt;Recipient Account:&lt;\/label&gt;\n        &lt;input type=<span class=\"hljs-string\">\"number\"<\/span> name=<span class=\"hljs-string\">\"recipient_account\"<\/span> value=<span class=\"hljs-string\">\"&lt;?= $inputs&#91;'recipient_account'] ?? '' ?&gt;\"<\/span> id=<span class=\"hljs-string\">\"recipient_account\"<\/span> placeholder=<span class=\"hljs-string\">\"Enter the recipient account\"<\/span>&gt;\n        &lt;small&gt;<span class=\"hljs-meta\">&lt;?<\/span>= $errors&#91;<span class=\"hljs-string\">'recipient_account'<\/span>] ?? <span class=\"hljs-string\">''<\/span> <span class=\"hljs-meta\">?&gt;<\/span>&lt;\/small&gt;\n    &lt;\/div&gt;\n\n    &lt;input type=<span class=\"hljs-string\">\"hidden\"<\/span> name=<span class=\"hljs-string\">\"token\"<\/span> value=<span class=\"hljs-string\">\"&lt;?= $_SESSION&#91;'token'] ?? '' ?&gt;\"<\/span>&gt;\n    &lt;button type=<span class=\"hljs-string\">\"submit\"<\/span>&gt;Transfer Now&lt;\/button&gt;\n&lt;\/form&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='post-php'>post.php <a href=\"#post-php\" class=\"anchor\" id=\"post-php\" title=\"Anchor for post.php\">#<\/a><\/h3>\n\n\n\n<p>The following code validates the token and form data:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\n\n\n<span class=\"hljs-keyword\">if<\/span>(filter_has_var(INPUT_POST, <span class=\"hljs-string\">'token'<\/span>)) {\n\t$token = $_POST&#91;<span class=\"hljs-string\">'token'<\/span>];\t\n\n\t<span class=\"hljs-keyword\">if<\/span> (!$token || $token !== $_SESSION&#91;<span class=\"hljs-string\">'token'<\/span>]) {\n\t\theader($_SERVER&#91;<span class=\"hljs-string\">'SERVER_PROTOCOL'<\/span>] . <span class=\"hljs-string\">' 405 Method Not Allowed'<\/span>);\n\t\t<span class=\"hljs-keyword\">exit<\/span>;\n\t}\n\n} <span class=\"hljs-keyword\">else<\/span> {\n\theader($_SERVER&#91;<span class=\"hljs-string\">'SERVER_PROTOCOL'<\/span>] . <span class=\"hljs-string\">' 405 Method Not Allowed'<\/span>);\n\t<span class=\"hljs-keyword\">exit<\/span>;\n}\n\n\n\n<span class=\"hljs-comment\">\/\/ Validate amount<\/span>\n$amount = filter_input(INPUT_POST, <span class=\"hljs-string\">'amount'<\/span>, FILTER_SANITIZE_NUMBER_INT);\n$inputs&#91;<span class=\"hljs-string\">'amount'<\/span>] = $amount;\n\n<span class=\"hljs-keyword\">if<\/span> ($amount) {\n\t$amount = filter_var(\n\t\t$amount,\n\t\tFILTER_VALIDATE_INT,\n\t\t&#91;<span class=\"hljs-string\">'options'<\/span> =&gt; &#91;<span class=\"hljs-string\">'min_range'<\/span> =&gt; <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-string\">'max_range'<\/span> =&gt; <span class=\"hljs-number\">5000<\/span>]]\n\t);\n\n\t<span class=\"hljs-keyword\">if<\/span> (!$amount) {\n\t\t$errors&#91;<span class=\"hljs-string\">'amount'<\/span>] = <span class=\"hljs-string\">'Please enter a valid amount (from $1 to $5000)'<\/span>;\n\t}\n} <span class=\"hljs-keyword\">else<\/span> {\n\t$errors&#91;<span class=\"hljs-string\">'amount'<\/span>] = <span class=\"hljs-string\">'Please enter the transfered amount.'<\/span>;\n}\n\n<span class=\"hljs-comment\">\/\/ validate account<\/span>\n$recipient_account = filter_input(INPUT_POST, <span class=\"hljs-string\">'recipient_account'<\/span>, FILTER_SANITIZE_NUMBER_INT);\n\n$inputs&#91;<span class=\"hljs-string\">'recipient_account'<\/span>] = $recipient_account;\n\n<span class=\"hljs-keyword\">if<\/span> ($recipient_account) {\n\t$recipient_account = filter_var($recipient_account, FILTER_VALIDATE_INT);\n\n\t<span class=\"hljs-keyword\">if<\/span> (!$recipient_account) {\n\t\t$errors&#91;<span class=\"hljs-string\">'recipient_account'<\/span>] = <span class=\"hljs-string\">'Please enter a valid recipient account'<\/span>;\n\t}\n} <span class=\"hljs-keyword\">else<\/span> {\n\t$errors&#91;<span class=\"hljs-string\">'recipient_account'<\/span>] = <span class=\"hljs-string\">'Please enter the recipient account.'<\/span>;\n} <span class=\"hljs-meta\">?&gt;<\/span>\n\n\n<span class=\"hljs-meta\">&lt;?php<\/span> <span class=\"hljs-keyword\">if<\/span> (!$errors) : <span class=\"hljs-meta\">?&gt;<\/span>\n\t&lt;section&gt;\n\t\t&lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">circle<\/span>\"&gt;\n\t\t\t&lt;<span class=\"hljs-title\">div<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">check<\/span>\"&gt;&lt;\/<span class=\"hljs-title\">div<\/span>&gt;\n\t\t&lt;\/<span class=\"hljs-title\">div<\/span>&gt;\n\n\t\t&lt;<span class=\"hljs-title\">h1<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">message<\/span>\"&gt;<span class=\"hljs-title\">You<\/span>'<span class=\"hljs-title\">ve<\/span> <span class=\"hljs-title\">transferred<\/span>&lt;\/<span class=\"hljs-title\">h1<\/span>&gt;\n\t\t&lt;<span class=\"hljs-title\">h2<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">amount<\/span>\"&gt;$&lt;?= $<span class=\"hljs-title\">amount<\/span> ?&gt;&lt;\/<span class=\"hljs-title\">h2<\/span>&gt;\n\n\t\t&lt;<span class=\"hljs-title\">a<\/span> <span class=\"hljs-title\">href<\/span>=\"&lt;?= <span class=\"hljs-title\">htmlspecialchars<\/span>($<span class=\"hljs-title\">_SERVER<\/span>&#91;'<span class=\"hljs-title\">PHP_SELF<\/span>']) ?&gt;\" <span class=\"hljs-title\">rel<\/span>=\"<span class=\"hljs-title\">prev<\/span>\"&gt;<span class=\"hljs-title\">Done<\/span>&lt;\/<span class=\"hljs-title\">a<\/span>&gt;\n\t&lt;\/<span class=\"hljs-title\">section<\/span>&gt;\n&lt;?<span class=\"hljs-title\">php<\/span> <span class=\"hljs-title\">endif<\/span> ?&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How the <code>post.php<\/code> works.<\/p>\n\n\n\n<p>First, check if the token from the INPUT_POST:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">if<\/span>(filter_has_var(INPUT_POST, <span class=\"hljs-string\">'token'<\/span>)) {<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>filter_input()<\/code> function returns false if the token is included in the HTTP POST request.<\/p>\n\n\n\n<p>Second, compare the sanitized token with the one stored in the <code>$_SESSION<\/code> variable:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">if<\/span> (!$token || $token !== $_SESSION&#91;<span class=\"hljs-string\">'token'<\/span>]) {\n    <span class=\"hljs-comment\">\/\/ process error<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If they&#8217;re not matched, we return the HTTP status code 405 (method not allowed) to the client using the <code>header()<\/code> function and immediately stops the script.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">header($_SERVER&#91;<span class=\"hljs-string\">'SERVER_PROTOCOL'<\/span>] . <span class=\"hljs-string\">' 405 Method Not Allowed'<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The remaining code sanitizes and validates the amount and recipient account. If there is no error, we show a confirmation message:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"php\"><span class=\"hljs-meta\">&lt;?php<\/span> <span class=\"hljs-keyword\">if<\/span> (!$errors) : <span class=\"hljs-meta\">?&gt;<\/span><\/span>\n\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"circle\"<\/span>&gt;<\/span>\n\t\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"check\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\t\t<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\n\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"message\"<\/span>&gt;<\/span>You've transferred<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"amount\"<\/span>&gt;<\/span>$<span class=\"php\"><span class=\"hljs-meta\">&lt;?<\/span>= $amount <span class=\"hljs-meta\">?&gt;<\/span><\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n\n\t\t<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"&lt;?= htmlspecialchars($_SERVER&#91;'PHP_SELF']) ?&gt;\"<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"prev\"<\/span>&gt;<\/span>Done<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n\t<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n<span class=\"php\"><span class=\"hljs-meta\">&lt;?php<\/span> <span class=\"hljs-keyword\">endif<\/span> <span class=\"hljs-meta\">?&gt;<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='summary'>Summary <a href=\"#summary\" class=\"anchor\" id=\"summary\" title=\"Anchor for Summary\">#<\/a><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CSRF attacks force users to execute an action against the site where they&#8217;re currently logged in.<\/li>\n\n\n\n<li>Use the <code>bin2hex(random_bytes(35))<\/code> to generate the one-time token.<\/li>\n\n\n\n<li>Check the submitted token with the one stored in the <code>$_SESSION<\/code> to prevent the CSRF attacks.<\/li>\n<\/ul>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<header>\n\t\t<div class=\"wth-question\">Did you find this tutorial useful?<\/div>\n\t\t<div class=\"wth-thumbs\">\n\t\t\t<button\n\t\t\t\tdata-post=\"1723\"\n\t\t\t\tdata-post-url=\"https:\/\/www.phptutorial.net\/php-tutorial\/php-csrf\/\"\n\t\t\t\tdata-post-title=\"PHP CSRF\"\n\t\t\t\tdata-response=\"1\"\n\t\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t\t<\/button>\n\n\t\t\t<button\n\t\t\t\tdata-response=\"0\"\n\t\t\t\tdata-post=\"1723\"\n\t\t\t\tdata-post-url=\"https:\/\/www.phptutorial.net\/php-tutorial\/php-csrf\/\"\n\t\t\t\tdata-post-title=\"PHP CSRF\"\n\t\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t\t<\/button>\n\t\t<\/div>\n\t<\/header>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\n\t\t\t<button class=\"btn btn-primary wth-btn-submit\">Send<\/button>\n\t\t\t<button class=\"btn wth-btn-cancel\">Cancel<\/button>\n\t\t\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>in this tutorial, you will learn about cross-site request forgery (CSRF) attack and how to prevent it in PHP.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":15,"menu_order":91,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1723","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/1723","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/comments?post=1723"}],"version-history":[{"count":5,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/1723\/revisions"}],"predecessor-version":[{"id":3289,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/1723\/revisions\/3289"}],"up":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/15"}],"wp:attachment":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/media?parent=1723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}