Jason_Wong Posted December 12, 2014 Share Posted December 12, 2014 There is a login page called login.php, after user type their username and password into textbox, then the page direct it to the page validate, which is validate.php. In validate.php, if user do not type anything, then direct it to the login.php again; if user type their username and password worng less than 3 times, then direct it to the login.php also. However, if user type their username and password more than 3 times, then direct it to the register.php. Question: i don't know how to make 3 attempts (maybe there are something worng in my page), it doesn't work, Please help, here is my validate.php <?php $loginErrorV = false; $loginErrorW = false; if(!empty($_POST['username']) && !empty($_POST['password']) && strlen($_POST['username'])!=0 && strlen($_POST['password'])!=0) { // $username = $_POST['username']; $password = $_POST['username']; //Connect to Database $conn = mysql_connect("localhost", "root", ""); if(!$conn){ die('Could not connect:'.mysql_error()); } mysql_select_db("logindb", $conn); // $sql = "Select count(username) as user_exist from logint where username = '$username' and password = '$password'"; $result = mysql_query($sql, $conn); $row = mysql_fetch_assoc($result); // if($row['user_exist'] == 1){ session_start(); $_SESSION['username'] = $username; header('Location: 10586740.html'); mysql_close($conn); } else { $loginErrorV = true; } } else { $loginErrorW = true; } if($loginErrorV){ if(isset($_COOKIE['login'])){ if($_COOKIE['login']<3){ header('Location:login.php'); $attempts = $_COOKIE['login'] + 1; } else { header('Location:register.php'); } } } if($loginErrorW){ header('Location:login.php'); } ?> Quote Link to comment Share on other sites More sharing options...
hansford Posted December 12, 2014 Share Posted December 12, 2014 I wouldn't attempt to store the data in a cookie. I would use something like $_SESSION['temp_username']['attempts'] to keep track of how many attempts. At the beginning of your script just check this value and redirect accordingly. Quote Link to comment Share on other sites More sharing options...
Jason_Wong Posted December 12, 2014 Author Share Posted December 12, 2014 Re hansford: I don't know what you mean exactly, because i am new in php. Can you explain more? Thank you very much! Quote Link to comment Share on other sites More sharing options...
hansford Posted December 12, 2014 Share Posted December 12, 2014 On a side note, there is usually a login link and sign up link which most people understand these days. If they keep attempting to login and failing...they should be able to click the forgot username/password link and get a hint or temp password emailed to them. A session will expire, but depending how long a cookie is set, they could forever be going to the sign up page even though they are just forgetful members. Let them try to login all day if they want because eventually they will: A) remember their login details B) click the link sign up link C) click the forgot username/password link Quote Link to comment Share on other sites More sharing options...
Jason_Wong Posted December 12, 2014 Author Share Posted December 12, 2014 Re hansford, but i wanna know more about attempts, like your $_SESSION['temp_username']['attempts'] Quote Link to comment Share on other sites More sharing options...
hansford Posted December 12, 2014 Share Posted December 12, 2014 When a user attempts to login. session_start(); // attempt to authenticate user with login // if login fails that's strike one $_SESSION['attempts'] += 1; if($_SESSION['attempts'] >= 3) { // you're being redirected to crack some rocks } else { // congrats you made it! } Quote Link to comment Share on other sites More sharing options...
mac_gyver Posted December 12, 2014 Share Posted December 12, 2014 you wouldn't want to store the number of login tries in a session variable either, since you can get a new empty session simply by not propagating the session id with the page request. to detect and count failed login attempts, you need to store the information in a database. by storing each failed attempt as a separate row, along with the date/time, you can get a count of the number of failed attempts for any username within a time interval to decide what action to take. edit: using this method will also let you detect if there has been a flood of attempts over a longer period of time, indicating someone is trying to break into the account. Quote Link to comment Share on other sites More sharing options...
hansford Posted December 12, 2014 Share Posted December 12, 2014 You don't even have to keep track of some temp name - the session id will be unique for that user and the attempts will only pertain to that user's session. Quote Link to comment Share on other sites More sharing options...
hansford Posted December 12, 2014 Share Posted December 12, 2014 That's a point - I take it for granted all pages are under session management. If you forget to restart a session on some page = you just lost your session. As Mac_gyver pointed out - the definitive way would be to store the attempts in the db. Just remember to delete this data when no longer needed or else everyone who makes a typo on login will be forever redirected to the signup page lol Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted December 12, 2014 Share Posted December 12, 2014 None of the above suggestions will work out, and the current code is horriby insecure with all those SQL injection vulnerabilities, plaintext passwords and whatnot. Right now, really all you have is a lot of mumbo-jumbo: The code looks like it's protecting your application, but anybody with a basic understanding of the mechanics can break it. That's useless. It's actually downright harmful, because it creates a false sense of security. Your users will think that their accounts are protected, but in reality you've (inadvertently) published their passwords on the Internet. I understand that you're new to PHP, and that's perfectly fine. But then you shouldn't make security promises you cannot keep. Be honest. Why not make a public website which is open to everybody? This has a lot of advantages: No complicated registration procedure, no stupid passwords. Less code, more time for the actual content of the site. Instead of spending hours on user management details, you can simply make a nice website. Think about it. The Internet would be a better place if we didn't have to enter a frigging password on every frigging website. If you absolutely must have passwords, then I strongly recommend that you postpone the project until you have a basic understanding of web programming. No, you can't just insert user input into query strings (never heard of Little Bobby Tables?). No, you can't store your user passwords as plaintext, because somebody might break into the database and steal them (that's actually very easy in your case). No, you can't store the log-in attempts in a cookie, because cookies are controlled by the user. They can be deleted or manipulated with just a few clicks in the browser. Try it yourself. For PHP basics, I recommend the PHP manual. If you look up your mysql_* functions, for example, you'll see a big red warning sign which says that those functions are long obsolete and have been replaced with the PDO library. For security basics, I recommend “Survive The Deep End” by Pádraic Brady (he also has an excellent blog). Checking the number of log-in attempts is fairly difficult, and even experienced programmers constantly get it wrong. First of all, yes, you have to store the attempts per user, not per cookie or whatever. Secondly, you have to increment and check the counter in a single operation. Otherwise, there's a small time gap between the check and the increment where users can make an arbitrary number of parallel requests. For example, let's say there's a delay of 1 second between your COUNT(*) query and the increment operation. If I make a new attempt every millisecond, then your server will accept all 1000 requests, because the counter still has the old value. Only after this it is finally incremented. This isn't just a theoretical threat. A stock browser and a small piece of JavaScript code are enough to send a large amount of parallel requests to a website (that's what browsers are for). So a simple SELECT followed by an UPDATE doesn't work. You need a single UPDATE query which also fetches the new counter value. As a basic example: The table CREATE TABLE users ( user_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, password CHAR(60) NOT NULL COMMENT 'bcrypt', login_attempts INT UNSIGNED NOT NULL DEFAULT 0, last_login_attempt DATETIME ) ENGINE InnoDB, CHARSET utf8mb4 ; database.php <?php define('DB_HOST', '...'); define('DB_NAME', '...'); define('DB_USER', '...'); define('DB_PASSWORD', '...'); define('DB_ENCODING', 'utf8mb4'); function get_database_connection() { $dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=' . DB_ENCODING . ''; $database = new PDO($dsn, DB_USER, DB_PASSWORD, array( PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, )); return $database; } login.php <?php require_once __DIR__ . '/database.php'; $database = get_database_connection(); /* * Increment the log-in attempts counter and fetch the new value with a single atomic operation * to prevent race conditions. * * If the last log-in attempt was more than 1 hour ago, the counter is reset. */ $loginAttemptsCheck = $database->prepare(' UPDATE users SET login_attempts = LAST_INSERT_ID(IF(NOW() > last_login_attempt + INTERVAL 1 MINUTE, 1, login_attempts + 1)), last_login_attempt = NOW() WHERE username = :username '); $loginAttemptsCheck->execute(array( 'username' => $_POST['username'], )); $loginAttempts = $database->lastInsertID(); if ($loginAttempts <= 3) { // check the password; if the log-in was successful, reset the counter to 0 } else { echo 'The account is temporarily locked because of more than three failed log-in attemps within one hour.'; } Note that a hard limit allows anybody to lock out your users simply by entering a wrong password again and again. A slightly less user-hostile approach would be a CAPTCHA: If the limit is exceeded, the user can unlock the account by solving some kind of puzzle. This also slows down attackers but doesn't lock out legtimate users entirely. Sounds complicated? Like I said, proper user management is a pain in the ass for both users and developers. Don't do it unless you absolutely have to. Quote Link to comment Share on other sites More sharing options...
NotionCommotion Posted December 15, 2014 Share Posted December 15, 2014 Nice approach. login_attempts = LAST_INSERT_ID(IF(NOW() > last_login_attempt + INTERVAL 1 MINUTE, 1, login_attempts + 1)), Should be login_attempts = LAST_INSERT_ID(IF(NOW() > last_login_attempt + INTERVAL 1 HOUR, 1, login_attempts + 1)), Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.