sKunKbad
Members-
Posts
1,832 -
Joined
-
Last visited
-
Days Won
3
Everything posted by sKunKbad
-
Have you tried running the update directly within mysql or phpMyAdmin to see if it works there?
-
THIS WORKS: <?php $exBday[0] = 11; $exBday[1] = 29; $exBday[2] = 2003; $months = array("", "January", "February", "March", "April", "May", "June", "July", "August", "Septemeber", "October", "November", "December"); $bdayMonth = $exBday[0]; if ($bdayMonth < 10) { $bdayMonth = ereg_replace("0", "", $bdayMonth); } $exBday2[0] = $months[$bdayMonth]; $birthday = "$exBday2[0] $exBday[1], $exBday[2]"; echo "<br>The birthday variable = " . $birthday; $this_month = (int) date("n"); // MONTH 1-12 $this_year = (int) date("Y"); // YEAR YYYY $today = (int) date("j"); echo "<br>$this_month = this_month, and $this_year = this_year, and today is $today"; $userAge = $this_year - $exBday[2]; echo "<br>The variable userAge = " . $userAge; if ($this_month < $exBday[0]) { $userAge = $userAge - 1; } if (($this_month == $exBday[0]) && ($today < $exBday[1])) { $userAge = $userAge - 1; } echo "<br>The variable userAge is now = " . $userAge; ?>
-
Where does $date come from. When I run as-is, all I get is: 12 = this_month, and 1969 = this_year
-
I played with your script, and here was the problem that I ran into: where $this_month is compared to $exBday[0], $exBday[0] is a string which the value is a name of a month, like "June". You need to keep $exBday a number value if you want to compare these variables. I admit, I had to add to your script just to figure this out. If you would supply more code I could probably come up with a solution. Here is what I was working with: <?php $exBday[0] = 6; $exBday[1] = 28; $exBday[2] = 2003; $months = array("", "January", "February", "March", "April", "May", "June", "July", "August", "Septemeber", "October", "November", "December"); $bdayMonth = $exBday[0]; if ($bdayMonth < 10) { $bdayMonth = ereg_replace("0", "", $bdayMonth); } $exBday[0] = $months[$bdayMonth]; $birthday = "$exBday[0] $exBday[1], $exBday[2]"; echo "<br>The birthday variable = " . $birthday; $this_year = 2008; $this_month = 5; $userAge = $this_year - $exBday[2]; echo "<br>The variable userAge = " . $userAge; if ($this_month < $exBday[0]) { $userAge = $userAge - 1; } if (($this_month == $exBday[0]) AND ($today < $exBday[1])) { $userAge = $userAge - 1; } echo "<br>The variable userAge is now = " . $userAge; ?>
-
such as? For instance, If you disable images, much of the text on the page "disappears", because it is the same color as the background.
-
Theres some accessibility issues, but if the school doesn't care, then I wouldn't either.
-
You might take a look at the search button on my site, and see how it is aligned. It looks more or less the same in all browsers / OSs
-
That really doesn't make much sense. The horizonal menu can have multiple tiers if necessary, but really there would be no need for the vertical menu. It would also require a 3 column site which I do not want. Sure, if you want to use javascript or some CSS solution, you can have multiple tiered menus. I just know that with my customers, who are mostly older people, many of which have computer skills that are weak at best, and many of which also have impaired vision, that these kinds of menus aren't accessible enough or simple enough for them. High school kids on the other hand would probably be in a different class of user (no pun intended). The mockup does look good though. I'm curious how you will code it, and looking forward to reviewing it later.
-
I have a business site that has a horizontal menu, and it has really hindered the growth of the site. Especially for a high school site, I'd expect that the site could eventually become much larger than anticipated, and I'd suggest using a vertical menu. Other than that, I do really like the color choices, the layout, and the overall professional look.
-
I found this error output at the bottom of the page. I'm on Mac FF3: Warning: Cannot modify header information - headers already sent by (output started at /home/nazca/public_html/game/pubheader.php:15) in /home/nazca/public_html/game/header.php on line 6
-
I have tried looking at your site on Mac FF3, and Win FF2, and on both I get: Notice: SSI.php was unable to load a session! This may cause problems with logout and other functions - please make sure SSI.php is included before *anything* else in all your scripts! in /home/ericr/public_html/community/SSI.php on line 166
-
[SOLVED] Problem with forgot password script
sKunKbad replied to iblackedout's topic in PHP Coding Help
I'm working on a script that is sort of specialized to my own login system, but I'll copy and paste the code here, and you can check it out as an example. <?php /* This script allows a user to recover their username, and reset their password if desired. A password reset link is sent to the user via email, and if followed, they have an opportunity to reset their password. The script is pretty complex, and could probably use some refining, but it does work well. CODE BY R.B.Gottier - www.brianswebdesign.com */ require_once("../app_top.inc.php"); if(!isset($get_p) && !isset($post_change_p)){ // If the user has just come to this page, OR the email address has been submitted for username or password recovery $fail = 0; if (isset($post_submit)){ // If the email address has been submitted if ($post_email == FALSE || $post_email == NULL){ $fail = 1; } if($fail != 1){ // If validation of the email variable was OK, check the database for the email address to see if there is a match, and return a user_id, hashed password, and firstname if available $clean_email = clean_for_query($post_email); $a = mysqli_query($db , "SELECT u.user_id,u.password,ua.firstname FROM users AS u,user_accounts AS ua WHERE u.user_id = ua.user_id AND ua.email = '$clean_email' LIMIT 1"); $numrows = mysqli_num_rows($a); if ($numrows == 0){ // If not match $fail = 1; }else{ // If there was a match then send an email to the user $row = mysqli_fetch_assoc($a); $password_half = str_split($row['password'] , 16); $reassembled_password = $password_half[1] . $password_half[0]; $reassembled_password .= "{$row['user_id']}"; $random_hash = md5(date('r', time())); $to = $clean_email; $subject = 'Your ' . SITE_NAME . ' account'; $headers = "From: " . SITE_NAME . " <" . ADMIN_EMAIL . ">\r\nReply-To: " . ADMIN_EMAIL . "\r\nReturn-Path: " . ADMIN_EMAIL; $headers .= "\r\nContent-Type: multipart/alternative; boundary=\"PHP-alt-".$random_hash."\""; $plain_text_content = "Hi {$row['firstname']},\n\n\nCopy and paste the following link into your browser if you can't click on it:\n\n" . this_page() . "?p=$reassembled_password\n\nYou can then reset your password, and gain access to your " . SITE_NAME . " account.\n\nThank you,\n\n" . SITE_NAME; $html_content = "Hi {$row['firstname']},<br />Follow the link provided below:<br><a href='" . this_page() . "?p=$reassembled_password'>RESET</a>.<br>You can then reset your password, and gain access to your " . SITE_NAME . " account.<br>Thank you,<br>" . SITE_NAME; //THIS MUST STAY PARKED OVER ON THE LEFT SIDE OF THE CODE *** DO NOT INDENT THIS TO KEEP THE CODE PRETTY OR IT WILL NOT WORK! $message = " --PHP-alt-$random_hash Content-Type: text/plain; charset=\"iso-8859-1\" Content-Transfer-Encoding: 7bit $plain_text_content --PHP-alt-$random_hash Content-Type: text/html; charset=\"iso-8859-1\" Content-Transfer-Encoding: 7bit $html_content --PHP-alt-$random_hash-- "; // END MESSAGE BODY AREA // The following line of code is only for development purposes: echo $to . "<br>" . $subject . "<br>" . $message . "<br>" . $headers . "<br>"; // Uncomment the following line in the production environment: //mail( $to, $subject, $message, $headers ); echo "<h2>Email Sent</h2><p>We have emailed you at $clean_email! This email will provide instructions on how to log in to your account.</p><p>If you don't receive this email shortly, check your spam/bulk email folder, or repeat this process.</p>"; mysqli_free_result($a); } } } if (!isset($post_submit) || $fail == 1){ //If the email address has not been submitted, or if the email address was not in the database if ($fail == 1){ // If the email address was not in the database echo '<h2 class="errorH2">Bad Email Address</h2> <div class="errorDiv"> <p style="padding-bottom:0px;">Your email address was not in our system. Please review the address you tried, try again, or call us directly.</p> </div>'; } // Display the form for either a user coming to the page for the first time, or if they didn't provide an email address that was in the database, prefill the email form field (prefill only works if the email address passed filtering) echo "<form action='" . this_page() . "' method='POST'> <h2>Forgot your login?</h2> <p>If your email address is in our database, we will send you information on how to reset your login.</p> <label for='email'>What is your email address?<label> <input id='email' name='email' type='text' maxlength='50'"; echo (isset($post_email) && $post_email != '') ? " value='" . htmlentities($post_email) . "'>" : ">"; echo " <input type='submit' name='submit' value='submit' /> </form>"; } }else{ // The user has followed the link in their email OR has submitted a new password if(isset($post_new_p) && $post_new_p != NULL && isset($post_change_p) && $post_change_p != '' && $post_new_p == $post_new_p_conf){ // If the user has submitted a new password and the password and password confirmation fields match if( strlen( $post_new_p ) > MAX_PASSWORD_LENGTH || strlen( $post_new_p ) < MIN_PASSWORD_LENGTH ){ // If the newly submitted password is more than 12 characters, or less than 7, send the user back to the form to change it echo "<h2 class='errorH2'>Password is too long or too short.</h2> <div class='errorDiv'> <p style='padding-bottom:0px;'>Your password must be between " . MIN_PASSWORD_LENGTH . " and " . MAX_PASSWORD_LENGTH . " characters in length.</p> <form action='" . this_page() . "' method='POST'> <label for='new_p'>Choose a new password (" . MIN_PASSWORD_LENGTH . " min / " . MAX_PASSWORD_LENGTH . " max)<label> <input id='new_p' name='new_p' type='text' /> <label for='new_p_conf'>Confirm new password<label> <input id='new_p_conf' name='new_p_conf' type='text' /> <input name='username' value='" . htmlentities($post_username) . "' type='hidden' /> <input name='old_p' value='$get_p' type='hidden' /> <input type='submit' name='change_p' value='submit' /> </form> </div>"; }else{ // The password is between MIN_PASSWORD_LENGTH and MAX_PASSWORD_LENGTH characters, and will be processed and updated in the database $password_half = str_split($post_old_p , 16); $reassembled_password = $password_half[1] . $password_half[0]; $clean_old_p = clean_for_query($reassembled_password); $enc_password = clean_for_query(md5(PASSWORD_SALT . $post_new_p)); if( strlen( $post_username ) > MAX_USERNAME_LENGTH ){ // At this point, a posted username that has more characters than MAX_USERNAME_LENGTH is an attack, since the value of $post_username comes from a hidden form field. die(); }else{ $clean_username = clean_for_query($post_username); } mysqli_query($db , "UPDATE `users` SET password='$enc_password' WHERE username='$clean_username' AND password='$clean_old_p'"); echo "<h2>Password Reset Confirmation</h2> <p>Once again, your username is <b>" . htmlentities($post_username) . "</b>. <br />Your new password is <b>" . htmlentities($post_new_p). "</b>. <br />Please write them down and proceed to login.</p> <p><a href='$thisDomain'>Continue</a></p>"; } }else{ // The user has either followed the link in the email, or the password and password confirmation fields DID NOT match if ( (isset($post_new_p) && isset($post_new_p_conf) && $post_new_p != $post_new_p_conf ) || (isset($post_new_p) && $post_new_p == '') || (isset($post_new_p_conf) && $post_new_p_conf == '') ) { // If the password and password confirmation fields didn't match, or if they were blank, an error message is shown echo "<p style='background-color:yellow;'>Password and confirmed password were not the same, or one or both were blank.</p>"; }else{ // If the user has followed the link in their email echo "<p style='background-color:white;'> </p>"; } $clean_get_p = clean_for_query($get_p); $password_half = str_split($clean_get_p , 16); $reassembled_password = $password_half[1] . $password_half[0]; $users_number = clean_for_query($password_half[2]); $z = mysqli_query($db , "SELECT u.user_id,u.username,ua.firstname FROM users AS u,user_accounts AS ua WHERE u.user_id = '$users_number' AND ua.user_id = '$users_number' AND password = '$reassembled_password' LIMIT 1"); $zrows = mysqli_num_rows($z); // Checks to see if anything is in the db. if ($zrows != 1){ // If the user could not be determined die(); }else{ // The user was determined by the get variable in the email link $row = mysqli_fetch_assoc($z); // The form is displayed so the user can reset their password echo "<p>Hi {$row['firstname']},<br><br>Your username is <b>{$row['username']}</b>. You will need this, so write it down.</p> <form action='" . this_page() . "' method='POST'> <label for='new_p'>Choose a new password (" . MIN_PASSWORD_LENGTH . " min / " . MAX_PASSWORD_LENGTH . " max)<label> <input id='new_p' name='new_p' type='text' maxlength='50' /> <label for='new_p_conf'>Confirm new password<label> <input id='new_p_conf' name='new_p_conf' type='text' maxlength='50' /> <input name='username' value='{$row['username']}' type='hidden' /> <input name='old_p' value='$get_p' type='hidden' /> <input type='submit' name='change_p' value='submit' /> </form>"; mysqli_free_result($z); } } } mysqli_close($db); ?> -
Perfect! Thanks!
-
MySQL client version: 5.0.45 Simplified for the question: CREATE TABLE `admins` ( `username` varchar(12) NOT NULL ) CREATE TABLE `users` ( `username` varchar(12) NOT NULL, ) SELECT users.username, admins.username FROM users, admins WHERE users.username = 'skunk' OR admins.username = 'skunk' I'm just trying to see if the username 'skunk' belongs to either an admin or a user, but I get a result set like this: username username skunk admin1 skunk admin2 skunk admin3 How can I make this query just return one row that matches 'skunk' and that's it. Like this: username skunk
-
[SOLVED] Problem with forgot password script
sKunKbad replied to iblackedout's topic in PHP Coding Help
Before you go too far with this script, you might want to think about security issues regarding emailing users their passwords. In my opinion, you would be better off emailing the user a special link with a query string that is unique to them. This query string could contain the users current encrypted password concatenated with their user ID, and perhaps a salt. When the user follows the link in their email, you would simply evaluate the query string, and allow the user to create their own password. This is more secure for a number of reasons, and the user doesn't have to change their password to something they can remember after you create a new password for them that is hard to remember. -
That error is telling you that you are redirecting to a page that is redirecting to itself, again and again infintely.
-
Problem in using the CURL to get html source code of a url
sKunKbad replied to ammu412's topic in PHP Coding Help
I am not saying that because a thread exists it means it's difficult to use. I am saying because of my experience and along with all the threads I see here about curl (must be 3 or 4 within a morning). Surely you can't deny that curl overly complicated easy to use. curl probably can do all of these things, but I don't want to have to learn all the curl flags and the combination of which should be used for a certain task, when there is an alternative which is much easier. Agreed there are many ways of doing something. However there is a lot of difference in the way the two methods in question are used. Aside from that curl is written in a procedural fashion. I personally prefer to program in an OOP fashion. Curl is very old and has not been updated inline with todays programming. Yes you could wrap it up in a class but I wouldn't want to be then one to have to do that. I consider cURL easy to use, and an essential part of my php apps. I've used it in many scripts, and my experience is that it is reliable. It does require more than just copy and pasting of code; it requires knowledge; and there are many tutorials out there that will get you started. We can't hold your hand every step of the way, and much of programming and php can't be figured out in a brief skim of a webpage. You'll have to read, and read, and read some more. What I think is funny, is that I provided a reliable solution to the original post, and this thread turned into an argument on how easy/hard cURL is to use. If it were so hard to use, then my code wouldn't work, but it does. Try it. -
Well, if it was me, I'd keep the prebuilt emails in a mysql database. If you have the subject line in one column, the message in another column, and headers in another column, all you would have to do is query the database for the specific emails you wish to send, and then loop through the rows, sending email as you go. Doing this would also give you the chance to have a non-html column, because usually when you send html email, you will want to send a text version also. If you will start putting together some code, and make a database, then when you get stuck we can help you. PHP is not like HTML, where you can easily copy and paste code and it will just work. You will need to learn. www.w3schools.com is a good place to learn, but the best stuff comes from books. I like the O'rielly book called "Programming PHP".
-
I had it varchar because I was storing the date formatted as date('c'), however, I switched now to time(), and made it int(10). I had taken a look at DATETIME, which is the same as date('c'), but it auto updates, which isn't really what I wanted for this field. It might not even matter, because this date only serves to be a user type salt in $_SESSION['token']. While I was at it, I changed some of the other column types too. Thanks for your input.
-
One thing worth mentioning, because I have been working on a login script lately, is that your login script does not address any of the common security vulnerabilities that are common to login scripts, and php/mysql for that matter. You've got a lot of work ahead of you if you really want something that is secure. If security isn't critical, you should at least protect your database by using mysql_real_escape_string on the variables that are in your queries. You might take a look at my previous posts. Within the last week I have been posting regarding a login script that I made, and it might give you some ideas.
-
I had read that having a separate table for admins was a good thing for security. This was my only reason for doing this. I really don't know if it matters, and it would obviously be way easier to code up this script if I had a column that designated an admin as an admin. I've never had one of my sites hacked, but I fear this, and try to code with security in mind. I suppose if some hacker had the ability to get at my database of users, then they would easily be able to see the admin database too. When considering security, there are opinions, and a lot to consider. I've spent a lot of time on this script, and I'm willing to spend more time on it, but at some point I just have to be done!
-
$email = array('deal1','deal2','deal3') foreach ($email as $html_email){ if ($html_email == 'on'){ mail( $to, $subject, $message, $headers ); } }
-
Problem in using the CURL to get html source code of a url
sKunKbad replied to ammu412's topic in PHP Coding Help
$ch = curl_init(); curl_setopt($ch, CURLOPT_USERAGENT, 'WhateverBrowser1.45'); curl_setopt($ch, CURLOPT_URL, 'http://www.yahoo.com'); curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt ($ch, CURLOPT_TIMEOUT, 60); $result = curl_exec($ch); echo "<pre>$result</pre>"; -
Well, I'm not sure if I did it exactly how you would have done it, but it works. I'm not sure if my database tables are as finely tuned as they could be, in terms of length and type. I'm going to include the whole script, minus the app_top.inc. What do you think now? <?php /* This script is used to check if a person is a user or admin. Cookies, must be enabled on the client's browser for this script to work. Another option would be to have the session ID appended to the URL by setting session.use_trans_sid to true in the server's php.ini file. Example usage for a user page: if (!isset($user_is_logged_in) || $user_is_logged_in == 'false') { //show login form }else{ // display user's content // the specific user is determined by the $clean_user_id variable } Example usage for an admin page: if (!isset($admin_is_logged_in) || $admin_is_logged_in == 'false') { //show login form }else{ // display admin's content } SQL to get started: CREATE TABLE `database_name`.`users` ( `user_id` SMALLINT NOT NULL AUTO_INCREMENT , `username` VARCHAR( 12 ) NOT NULL , `password` VARCHAR( 32 ) NOT NULL , `timestamp` VARCHAR( 26 ) NOT NULL , `login_hold` INT NOT NULL DEFAULT '0', PRIMARY KEY ( `user_id` ) , UNIQUE ( `username` ) ) ENGINE = InnoDB; CREATE TABLE `database_name`.`admins` ( `admin_id` SMALLINT NOT NULL AUTO_INCREMENT , `username` VARCHAR( 12 ) NOT NULL , `password` VARCHAR( 32 ) NOT NULL , `timestamp` VARCHAR( 26 ) NOT NULL , `login_hold` INT NOT NULL DEFAULT '0', PRIMARY KEY ( `admin_id` ) , UNIQUE ( `username` ) ) ENGINE = InnoDB; CREATE TABLE `database_name`.`user_login_attempts` ( `user_id` SMALLINT NOT NULL , `attempt_count` TINYINT NOT NULL DEFAULT '0', `last_attempt` INT NOT NULL ) ENGINE = InnoDB; CREATE TABLE `database_name`.`ip_login_attempts` ( `IPaddr` VARCHAR( 16 ) NOT NULL , `attempt_count` TINYINT( 2) NOT NULL , `login_hold` INT NULL DEFAULT '0', `last_attempt` INT NOT NULL ) ENGINE = InnoDB; CREATE TABLE `database_name`.`admin_login_attempts` ( `admin_id` SMALLINT NOT NULL , `attempt_count` TINYINT NOT NULL DEFAULT '0', `last_attempt` INT NOT NULL ) ENGINE = InnoDB; Users and admins will still need to be able to log out. Logging out usually requires that the session is unset, and that the user or admin is redirected to somewhere. */ // auto strip slashes and escape for db query function clean_for_query($data){ global $db; if(get_magic_quotes_gpc()){ // strip slashes and let mysql_real_escape_string do the work $data = stripslashes($data); } $data = mysqli_real_escape_string($db , trim($data)); return $data; } // auto clean and extract POST vars foreach($_POST as $post_key => $post_value){ if($post_key == 'email'){ $post_email = filter_input(INPUT_POST, 'email' , FILTER_VALIDATE_EMAIL); }else{ ${"post_$post_key"} = filter_input(INPUT_POST, "$post_key" , FILTER_SANITIZE_STRING); } } // initialize some variables $user_is_logged_in = 'false'; $login_error = 0; $admin_is_logged_in = 'false'; $admin_login_error = 0; // check if this is a login form submission if(isset($post_submit_login) && $post_submit_login == 'submit'){ // If the form post did not come from the same page on the development or production server, according to the HTTP_REFERER value, then the form post is an attack if (isset($_SERVER['HTTP_REFERER']) && !stristr($_SERVER['HTTP_REFERER'], $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"] )){ die(); } // If the POST vars did not pass validation if ($post_login_username == FALSE || $post_login_username == NULL || $post_login_password == FALSE || $post_login_password == NULL){ $login_error = 1; $user_is_logged_in = 'false'; $admin_login_error = 1; $admin_is_logged_in = 'false'; } // A username or password can not be more than 12 characters, and if either posted values are larger than 12 characters, login fails if( strlen( $post_login_username ) > MAX_USERNAME_LENGTH || strlen( $post_login_password ) > MAX_PASSWORD_LENGTH ){ $login_error = 1; $user_is_logged_in = 'false'; $admin_login_error = 1; $admin_is_logged_in = 'false'; } // check if the remote IP address is on hold $ip_on_hold = 0; if( isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] != '' && $_SERVER['REMOTE_ADDR'] != NULL ){ $clean_remote_ip = clean_for_query($_SERVER['REMOTE_ADDR']); $k = mysqli_query($db , "SELECT login_hold FROM `ip_login_attempts` WHERE IPaddr = '$clean_remote_ip' LIMIT 1"); $l = mysqli_num_rows($k); if($l == 1){ $row = mysqli_fetch_assoc($k); if ($row['login_hold'] > time() ){ $user_is_logged_in = 'false'; $login_error = 1; $ip_on_hold = 1; } } mysqli_free_result($k); } // check if the user is on hold $user_on_hold = 0; $clean_login_username = clean_for_query($post_login_username); $m = mysqli_query($db , "SELECT login_hold FROM `users` WHERE username = '$clean_login_username' LIMIT 1"); $n = mysqli_num_rows($m); if($l == 1){ $row = mysqli_fetch_assoc($m); if ($row['login_hold'] > time() ){ $user_is_logged_in = 'false'; $login_error = 1; $user_on_hold = 1; } } mysqli_free_result($m); // check if the admin is on hold $admin_on_hold = 0; $clean_login_username = clean_for_query($post_login_username); $m = mysqli_query($db , "SELECT login_hold FROM `admins` WHERE username = '$clean_login_username' LIMIT 1"); $n = mysqli_num_rows($m); if($l == 1){ $row = mysqli_fetch_assoc($m); if ($row['login_hold'] > time() ){ $admin_is_logged_in = 'false'; $admin_login_error = 1; $admin_on_hold = 1; } } mysqli_free_result($m); // if there was no error with login form submission validation, check if the user's username and password match a database row if($login_error != 1){ $clean_login_username = clean_for_query($post_login_username); $clean_login_password = clean_for_query($post_login_password); $super_password = md5(PASSWORD_SALT . $clean_login_password); $a = mysqli_query($db , "SELECT * FROM `users` WHERE username = '$clean_login_username' AND password = '$super_password' LIMIT 1"); $b = mysqli_num_rows($a); if($b == 1){ // if they match, then add some session keys, and $user_is_logged_in = 'true' $row = mysqli_fetch_assoc($a); $_SESSION['user_id'] = $row['user_id']; $fingerprint = $row['timestamp']; session_regenerate_id(); $_SESSION['user_token'] = md5($fingerprint . session_id() . $_SERVER['HTTP_USER_AGENT']); $user_is_logged_in = 'true'; mysqli_query($db , "UPDATE `users` SET login_hold = 0 WHERE user_id = '{$row['user_id']}' LIMIT 1"); mysqli_query($db , "DELETE FROM `user_login_attempts` WHERE user_id = '{$row['user_id']}' LIMIT 1"); if( isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] != '' && $_SERVER['REMOTE_ADDR'] != NULL ){ // clean up the ip_login_attempts log $clean_remote_ip = clean_for_query($_SERVER['REMOTE_ADDR']); mysqli_query($db , "DELETE FROM `ip_login_attempts` WHERE IPaddr = '$clean_remote_ip' LIMIT 1"); } }else{ // if they don't match, then the form submission matched no user $login_error = 1; $user_is_logged_in = 'false'; } mysqli_free_result($a); } // if there was no error with login form submission validation, check if the admin's username and password match a database row if($admin_login_error != 1){ $clean_login_username = clean_for_query($post_login_username); $clean_login_password = clean_for_query($post_login_password); $super_password = md5(PASSWORD_SALT . $clean_login_password); $a = mysqli_query($db , "SELECT * FROM `admins` WHERE username = '$clean_login_username' AND password = '$super_password' LIMIT 1"); $b = mysqli_num_rows($a); if($b == 1){ // if they match, then add some session keys, and $admin_is_logged_in = 'true' $row = mysqli_fetch_assoc($a); $_SESSION['admin_id'] = $row['admin_id']; $fingerprint = $row['timestamp']; session_regenerate_id(); $_SESSION['admin_token'] = md5($fingerprint . session_id() . $_SERVER['HTTP_USER_AGENT']); $admin_is_logged_in = 'true'; mysqli_query($db , "UPDATE `admins` SET login_hold = 0 WHERE admin_id = '{$row['admin_id']}' LIMIT 1"); mysqli_query($db , "DELETE FROM `admin_login_attempts` WHERE admin_id = '{$row['admin_id']}' LIMIT 1"); if( isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] != '' && $_SERVER['REMOTE_ADDR'] != NULL ){ // clean up the ip_login_attempts log $clean_remote_ip = clean_for_query($_SERVER['REMOTE_ADDR']); mysqli_query($db , "DELETE FROM `ip_login_attempts` WHERE IPaddr = '$clean_remote_ip' LIMIT 1"); } }else{ // if they don't match, then the form submission matched no admin $admin_login_error = 1; $admin_is_logged_in = 'false'; } mysqli_free_result($a); } $try_ip = 0; // If a login attempt was made with an actual user's username, but the password was wrong, log the attempt if( $login_error == 1 ){ $clean_login_username = clean_for_query($post_login_username); $e = mysqli_query($db , "SELECT user_id FROM users WHERE username ='$clean_login_username' LIMIT 1"); $f = mysqli_num_rows($e); if ( $f == 1 ){ // If the post contains a real username $row = mysqli_fetch_assoc($e); $failed_user_id = $row['user_id']; mysqli_free_result($e); $i = mysqli_query($db , "SELECT attempt_count FROM user_login_attempts WHERE user_id ='$failed_user_id' LIMIT 1"); $j = mysqli_num_rows($i); if ( $j == 1 ){ // If the user already has a failed login attempt $row = mysqli_fetch_assoc($i); $previous_attempts = $row['attempt_count']; $current_attempts = $previous_attempts + 1; $hold_time = time() + ( LOGIN_RESTRICTION_MINS * 60); if ($current_attempts >= LOGIN_ATTEMPT_LIMIT) { // set or reset the login hold if the user has LOGIN_ATTEMPT_LIMIT failed login attempts or greater mysqli_query($db, "UPDATE `users` SET login_hold = '$hold_time' WHERE user_id = '$failed_user_id'"); } mysqli_query($db, "UPDATE `user_login_attempts` SET attempt_count = '$current_attempts' , last_attempt = " . time() . " WHERE user_id = '$failed_user_id'"); }else{ // Else create a database row to start loggin failed login attempts mysqli_query($db, "INSERT INTO `user_login_attempts` (user_id,attempt_count,last_attempt) VALUES ('$failed_user_id',1," . time() . ")"); } mysqli_free_result($i); }else{ $try_ip = 1; } } // If a login attempt was made with an actual admin's username, but the password was wrong, log the attempt if( $admin_login_error == 1 ){ $clean_login_username = clean_for_query($post_login_username); $e = mysqli_query($db , "SELECT admin_id FROM admins WHERE username ='$clean_login_username' LIMIT 1"); $f = mysqli_num_rows($e); if ( $f == 1 ){ // If the post contains a real admin's username $row = mysqli_fetch_assoc($e); $failed_admin_id = $row['admin_id']; mysqli_free_result($e); $i = mysqli_query($db , "SELECT attempt_count FROM admin_login_attempts WHERE admin_id ='$failed_admin_id' LIMIT 1"); $j = mysqli_num_rows($i); if ( $j == 1 ){ // If the admin already has a failed login attempt $row = mysqli_fetch_assoc($i); $previous_attempts = $row['attempt_count']; $current_attempts = $previous_attempts + 1; $hold_time = time() + ( LOGIN_RESTRICTION_MINS * 60); if ($current_attempts >= LOGIN_ATTEMPT_LIMIT) { // set or reset the login hold if the admin has LOGIN_ATTEMPT_LIMIT failed login attempts or greater mysqli_query($db, "UPDATE `admins` SET login_hold = '$hold_time' WHERE admin_id = '$failed_admin_id'"); } mysqli_query($db, "UPDATE `admin_login_attempts` SET attempt_count = '$current_attempts' , last_attempt = " . time() . " WHERE admin_id = '$failed_admin_id'"); }else{ // Else create a database row to start loggin failed login attempts mysqli_query($db, "INSERT INTO `admin_login_attempts` (admin_id,attempt_count,last_attempt) VALUES ('$failed_admin_id',1," . time() . ")"); } mysqli_free_result($i); }else{ $try_ip += $try_ip; } } // If a login attempt was made with no match for user's username or admin's username, log the attempt by IP address (if possible) if($try_ip == 2){ if(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] != '' && $_SERVER['REMOTE_ADDR'] != NULL){ $clean_remote_ip = clean_for_query($_SERVER['REMOTE_ADDR']); $g = mysqli_query($db , "SELECT attempt_count FROM ip_login_attempts WHERE IPaddr = '$clean_remote_ip'"); $h = mysqli_num_rows($g); if ( $h == 1 ){ $row = mysqli_fetch_assoc($g); $previous_attempts = $row['attempt_count']; $current_attempts = $previous_attempts + 1; $hold_time = time() + ( LOGIN_RESTRICTION_MINS * 60); if ($current_attempts >= LOGIN_ATTEMPT_LIMIT) { mysqli_query($db, "UPDATE `ip_login_attempts` SET attempt_count = '$current_attempts', last_attempt = '" . time() . "', login_hold = '$hold_time' WHERE IPaddr = '$clean_remote_ip'"); }else{ mysqli_query($db, "UPDATE `ip_login_attempts` SET attempt_count = '$current_attempts', last_attempt = '" . time() . "' WHERE IPaddr = '$clean_remote_ip'"); } }else{ mysqli_query($db, "INSERT INTO `ip_login_attempts` (IPaddr,attempt_count,last_attempt) VALUES ( '$clean_remote_ip' , 1 , " . time() . ")"); } mysqli_free_result($g); } } } // if the user or admin is not logging in through the form, we need to check who they are // the session variables are used to see if the person is a user if(isset($_SESSION['user_id']) && isset($_SESSION['user_token'])){ $clean_user_id = clean_for_query($_SESSION['user_id']); $c = mysqli_query($db , "SELECT * FROM `users` WHERE user_id = '$clean_user_id' LIMIT 1"); $d = mysqli_num_rows($c); if($d == 1){ // if there was a match for the user's ID, we proceed to check the token $row = mysqli_fetch_assoc($c); $fingerprint = $row['timestamp']; if($_SESSION['user_token'] = md5($fingerprint . session_id() . $_SERVER['HTTP_USER_AGENT'])){ // user's timestamp, session ID, and user agent must stay the same session_regenerate_id(); $user_is_logged_in = 'true'; }else{ // if user's timestamp, session ID, and user agent are not the same, they will have to log in again $login_error = 1; $user_is_logged_in = 'false'; } } mysqli_free_result($c); } // the session variables are used to see if the person is an admin if(isset($_SESSION['admin_id']) && isset($_SESSION['admin_token'])){ $clean_admin_id = clean_for_query($_SESSION['admin_id']); $c = mysqli_query($db , "SELECT * FROM `admins` WHERE admin_id = '$clean_admin_id' LIMIT 1"); $d = mysqli_num_rows($c); if($d == 1){ // if there was a match for the admin's ID, we proceed to check the token $row = mysqli_fetch_assoc($c); $fingerprint = $row['timestamp']; if($_SESSION['admin_token'] = md5($fingerprint . session_id() . $_SERVER['HTTP_USER_AGENT'])){ // admin's timestamp, session ID, and user agent must stay the same session_regenerate_id(); $admin_is_logged_in = 'true'; }else{ // if admin's timestamp, session ID, and user agent are not the same, they will have to log in again $admin_login_error = 1; $admin_is_logged_in = 'false'; } } mysqli_free_result($c); } // If max logins are preventing a user / admin / attacker from logging in, show this message if ((isset($user_on_hold) && $user_on_hold == 1) || (isset($admin_on_hold) && $admin_on_hold == 1) || (isset($ip_on_hold) && $ip_on_hold == 1)){ echo "You have exceeded the login attempts allowed and must wait " . LOGIN_RESTRICTION_MINS . " minutes before trying again. Please come back later and try again."; } ?> I also made a little cron for cleanup: <?php /* This script is used to clean up the old login attempts in the database. */ require_once("app_top.inc.php"); $old_hold = time() - ( LOGIN_RESTRICTION_MINS * 60); echo $old_hold; mysqli_query($db , "DELETE FROM `user_login_attempts` WHERE last_attempt < '$old_hold'"); mysqli_query($db , "DELETE FROM `admin_login_attempts` WHERE last_attempt < '$old_hold'"); mysqli_query($db , "DELETE FROM `ip_login_attempts` WHERE last_attempt < '$old_hold'"); ?>
-
I also think this is the better solution, but I am concerned that a true attacker would know to purge cookies (or not have them enabled at all). Login attempts could be stored in a database, but checking IP addresses is unreliable, and there really isn't anything else to check that really IDs a connection. I suppose ALL of this could be done, and it would make things tougher for an attacker, but I'm guessing that the old saying, "locks keep honest people honest" sort of applies to login security. I think I will store the login attempts in a cookie, and consider the script done.