{"id":2410,"date":"2015-02-03T02:27:44","date_gmt":"2015-02-03T02:27:44","guid":{"rendered":"http:\/\/www.sitekickr.com\/blog\/?p=2410"},"modified":"2015-02-03T11:41:09","modified_gmt":"2015-02-03T11:41:09","slug":"simplest-prevent-brute-force-logins","status":"publish","type":"post","link":"https:\/\/www.sitekickr.com\/blog\/simplest-prevent-brute-force-logins\/","title":{"rendered":"The simplest possible way to prevent brute-force logins"},"content":{"rendered":"<p>So I&#8217;m gearing up to protect one of my login forms against brute-force authentication attacks (essentially a bot guessing at a password over and over hoping for success).<\/p>\n<p>I&#8217;ve read up on it and every solution I find appears to be more complex than it needs to be (involving adding multiple additional fields to the database).<\/p>\n<p>After tabling it for a few days, an idea hit me. We can do this with very little code and one additional database field, as long as we setup a cron job to help us out.<\/p>\n<p>Let me explain in three simple steps&#8230;<\/p>\n<h3>The database field<\/h3>\n<p>Just add one field to your users table: \u00a0<strong>login_attempts tinyint default 0<\/strong><\/p>\n<h3>The code<\/h3>\n<p>During your authentication check, add <strong>login_attempts<\/strong> to your query&#8217;s SELECT statement.<\/p>\n<p>Then, before checking the password, execute something like this (illustrated with PHP)<\/p>\n<pre class=\"prettyprint\"><code>if ($user['login_attempts'] &gt; 5) {\r\n  header('Location: ..\/?errors=Too many failed login attempts. \r\n           Please try again in 5 minutes.');\r\n  exit();\r\n}\r\n\r\n....\r\n\r\n\/* if login fails *\/\r\nUPDATE\t\t users\r\nSET\t\t login_attempts = login_attempts + 1\r\nWHERE\t\t email = :email\r\n\r\n<\/code><\/pre>\n<h3>The cron<\/h3>\n<p>A script that runs every 5 minutes and simply runs the following SQL statement:<\/p>\n<pre>UPDATE users\r\n SET login_attempts = 0<\/pre>\n<p>&nbsp;<\/p>\n<p>Perhaps I&#8217;ve under-thought this one, so let me know if anyone sees a hole in my thinking!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Protecting your login from brute-force attacks is much simpler than you might think. With three quick updates to your code and database, you&#8217;ll be all set.<\/p>\n","protected":false},"author":1,"featured_media":2411,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"amp_status":""},"categories":[123],"tags":[253],"_links":{"self":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/2410"}],"collection":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/comments?post=2410"}],"version-history":[{"count":7,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/2410\/revisions"}],"predecessor-version":[{"id":2418,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/2410\/revisions\/2418"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/media\/2411"}],"wp:attachment":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/media?parent=2410"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/categories?post=2410"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/tags?post=2410"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}