I want that once the person enters their information for log in it brings them to home.php. my current code is this:
if (isset($_POST["user_login"]) && isset($_POST["password_login"])) {
$user_login = preg_replace('#[^A-Za-z0-9]#i', '', $_POST["user_login"]);
$password_login = preg_replace('#[^A-Za-z0-9]#i', '', $_POST["password_login"]);
$md5password_login = md5($password_login);
$sql = mysql_query("SELECT id FROM users WHERE username='$user_login' AND password='$md5password_login_md5' AND closed='no' LIMIT 1");
$userCount = mysql_num_rows($sql);
if ($userCount == 1) {
while($row = mysql_fetch_array($sql)){
$id = $row["id"];
}
$_SESSION["id"] = $id;
$_SESSION["user_login"] = $user_login;
$_SESSION["password_login"] = $password_login;
header("location: home.php");
exit();
} else {
echo 'That Log In information is incorrect, please try again';
exit();
}
}
?>
I gather this is (hopefully) a testing script, or a way to learn. That's cool, but there's multiple things that I'd suggest you look into:
You're using mysql_* functions. These are now deprecated. It's suggested to use mysqli or PDO
You're using md5 for password storage. Please use password_hash and password_verify instead
Using regexes to validate data isn't a bad idea, and credit for using them. However, you might want to give the regex a quantifier so it matches more than just one character. Just put a + after your [^A-Za-z0-9] blocks
The main reason your header might not be working is that it is case sensitive, and should be a full URL. See the notes on the PHP manual page for header()
Have a look at PHP The Right Way. You're starting out well, but without guidance you're going down paths that'll be problematic later.
Related
I've created a login page and I'm using Cookies. Down below is the code for Login Page:
Register
<?php
session_start();
if(isset($_POST['submitted'])){
$errors = array();
$mysqli = new mysqli('localhost', 'db123', 'db123', 'db123');
$username = $_POST['username'];
$result = $mysqli->query("SELECT * FROM registered_users WHERE phone_number = '$username'");
$data = mysqli_fetch_assoc($result);
if($result->num_rows == 0) {
echo 'Username Not Found!';
} elseif($data['otp_verified'] === 'false'){
echo 'OTP Not Verified, Click Here To Verify Your Number';
}
else{
$encryptpass=md5($_POST['password']);
$cookie_username = $_POST['username'];
if($encryptpass == $data['password']){
echo 'Login Is Verified';
$Month = 86400 + time();
setcookie('user', $cookie_username, $Month);
header("location:dashboard.php");
}
else{
echo 'Login/Password Incorrect :(';
}
}
$mysqli->close();
}
?>
And Finally, Here's the code for dashboard.php and all other pages which are restricted:
<?php
session_start();
if(!isset($_COOKIE['user']))
{
header("location:index.php");
die();
}
?>
My Questions:
1. How Secure Is This Login System?
2. How I can improve it?
Thanks in advance :)
Here's a non-exhaustive list of problems/solutions:
Your code is difficult to read because it is not properly indented.
You should use prepared statemens to guard against SQL-injection.
You give hints to hackers by having different error messages. When the username is correct and the password wrong you say: "Login/Password Incorrect :(", but if the username is wrong you say: "Username Not Found!". That way a hacker can know if an username is correct, and half the job is done.
Better not use md5() for password encryption.
Use password_hash() for handling passwords.
Do not store the username in a cookie. Again, you're leaking information.
Don't use cookies, there's just no need to do that, use sessions and store information on the server, not on the user's machine.
You seem to have stored usernames as phone_number. So which one is it? It is either an username or a phone number, it cannot be both. Even if you use phone numbers as user names, call them what they are.
Sloppy coding: $errors = array(); is not used anywhere. You don't check the result of new mysqli(), the connection might fail. Same is true for $mysqli->query().
You take care to close the database, but then why don't you release the query result with $result->close();? Either do both, or none.
Security is a difficult topic, it's really hard to get it right, and what might be good today, might be bad tomorrow.
Its very unsecure
there can be sql injections (because the username goes directly to the databasa)
md5 is obsolete since years
you save the username unencrypted
So i have written this code for my login page, but the problem is that its only able to login and not able to tell the user that the username or password was incorrect. Some help would be nice
<?php
session_start();
include 'dbh.php';
$uid = $_POST['uid'];
$pwd = $_POST['pwd'];
$sql = "SELECT * FROM user WHERE uid='$uid' AND pwd='$pwd'";
$result = mysqli_query($conn, $sql);
if (!$row = mysqli_fetch_assoc($result)) {
echo "your username or password is incorrect!";
} else {
$_SESSION['id'] = $row['id'];
}
header("Location: index.php");
Your if condition should be like this:
$row = mysqli_fetch_assoc($result)
if (!$row) {
echo "your username or password is incorrect!";
} else {
$_SESSION['id'] = $row['id'];
}
Also, the way you are doing is complete unsafe, and is vulnerable to SQL injection, it is better to use prepared statements
You don't provide much background. It would be essential to know index.php at least.
But I guess, the problem you face is that the script redirects to index.php independently from the outcome of the if-else before. So, you will always see login-behavior. You should move the header("Location: index.php"); into the else-branch after the $_SESSION statement.
Also, be sure that the session is deleted in some logout during your testing.
Remark to the other answers:
(I cannot comment yet, so I put the comment here.) The other answers tell you not to use
if( ! $row = mysqli_fetch_assoc($result) ) { ... } else { ... }
I agree that it is not a nice way of programming. But PHP actually allows it. $row will get the contents of mysqli_fetch_assoc( $result ). And additionally the if statement will be executed if that content evaluates to false. It's nicer to use
$row = mysqli_fetch_assoc($result);
if( ! $row ) { ... } else { ... }
But I do not think that will solve your problem.
Additional remark:
The comments are right that your code should only be used for practicing not for real-world web applications. It allows SQL injection because $uid and $pwd are not escaped. And the password is stored in plaintext in your database. No reasonable user of a normal web page would tolerate that.
= is not a valid comparison operator in php. You must use == or ===.
In this case you also want to find if the two values are equal, and simply adding a ! before $row will not work. You should use
if ($row !== mysqli_fetch_assoc($result)) {
instead.
Furthermore, your code is very vulnerable and your database can be broken into within minutes and all passwords obtained if you choose to simply leave it like this. You should look into Prepared Statements (to prevent SQL injections which can access your database without proper authentication by abusing your input fields) and you should also never leave your passwords stored in plaintext. They should always be hashed, and even better, salted.
Something weird is happening with the following code. Instead of completely redirecting. It loads the page of the redirect into the login page and mixes things up.
Q1: How do i make a complete redirect.
- session start is the first line
- There's nothing being output before header.
- As for spaces, I'm not sure what will count as a space in the below script.
Q2: How do i preg_replace a string to only allow both lower cases and uppercases and 0 - 9 numbers and again how do i preg replace emaail to allow the '#' charecter and alphanumerics.
Q3: What's the best way to check if the user trying to login matches exactly the registered user?
Q4: What danger can a hacker do with my session variables?
PHP CODE
<?php
session_start();
require_once 'db_conx.php';
$email = preg_replace ('#[^A-Z, 0-9 ]#i', '', $_POST['email']);
$pwd = preg_replace ('#[^A-Z, 0-9 ]#i', '', $_POST['pwd']);
if ($uname == '' || $pwd == ''){
echo '<span style="color:#F00">Please fill in all login details.</span>';
} else {
$Result = mysql_query("SELECT * FROM users WHERE uemail = '$uname' && pwd = '$pwd'")
or die (mysql_error());
while($row = mysql_fetch_array($Result)){
$_SESSION['Sname'] = $row['firstname'];
$_SESSION['Slname'] = $row['lastname'];
$_SESSION['SUid'] = $row['uid'];
$_SESSION['Semail'] = $row['uemail'];
$_SESSION['Suid'] = $row['uid'];
$_SESSION['Szip'] = $row['zip'];
}
if (mysql_num_rows($Result) > 0){
header ('Location: ../user.php');
} else {
echo '<span style="color:#F00">Your account details do not match, please check your details and try again or try to recover your account if you forgot your password</span>';
}
}
?>
Thanks.
Q1
instead of using header( 'Location...)
you can use
echo '<meta http-equiv="refresh" content="0; URL= http://something.com">';
EDIT
i believe you can also use the following. the die should allow for the redirect, but in my experience it doesn't always get along with jquery.
header('Location: http://something.com');
die();
This is especially useful if you are using event.preventDefault(); in jquery on the same page, which will almost always cause header location redirects to be ignored. this method is also appropriate when you are using get requests to include a php page in your index file, causing a url like http://somesite.com/index.php?page=home
EDIT the above information was wrong it wasn't working for me because php had already sent the headers. i'm an idiot.
instead of this meta refresh, you could do this which should produce the desired result.
echo '<script type="text/javascript">window.location = "yoururlhere"</script>';die;
Q2
$step1 = preg_replace('#[^A-Z, 0-9 ]#i', $_POST["variable"]);
$step2 = strtolower($step1);
echo $step2;
Q3
This is a tough question to answer, but basically you want to hash there password, then check if it matches the password in the db. heres a brief pseudocode.
$username = $db->real_escape_string(strip_tags($_POST["username"]));
$password = hash('sha512', $salt.$_POST["Password"});
$db->query("SELECT * FROM `usertable` WHERE `Username`='$username' AND `Password`='$password' AND Username IS NOT NULL AND Username != '' LIMIT 1");
$result = $db->get();
if(!$result){
//the query returned a null result, so the username or password was incorrect.
}else{
//set user session and log them in.
}
Q4
I'm no expert, but it all depends on the architecture of your application and how you are setting sessions and cookies.in my opinion look into using formkeys and preventing xss, rfi, sql injection and lfi, then worry about session variables. the experience gained tackling the aforementioned problems will give you confidence and a broader understanding when attempting to secure your user sessions.
further information can be obtained from php.net/manual/en/session.security.php and stackoverflow.com/questions/328/php-session-security
thanks to the suggestions of DanFromGermany who improved on this answer.
I'm kinda new to the OOP(? If this IS OOP, I don't know) language, and I'm trying to make a simple login-proccess, with MySQLi. The problem are, that the code doesn't work. I can't login (and It's not showing me any errors) and I can't register an new account (same problem) - It's like the code are dead or something.
I'm not sure I've done it right, but this is my best, so far. 'cause I'm new to OOP(?).
Index.php:
<?php
if(isset($_POST['submit'])) {
$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string(md5($_POST['password']));
$userControl = "SELECT * FROM users WHERE username='".$username."' AND password='".$password."'";
$userControlResult = $mysqli->query($userControl);
if($mysqli->num_rows($userControlResult) > 1) {
$userRow = $mysqli->fetch_assoc($userControlResult);
$dbid = $userRow['id'];
$dbuser = $userRow['username'];
$_SESSION['id'] = $dbid;
$_SESSION['username'] = $dbuser;
header("location: me.php");
die();
} else {
echo "<div class='errorField'>Användarnamnet eller lösenordet är fel!</div>";
}
}
?>
I suppose that if I can solve the first error, I can solve the second too.
Thanks!
Many things I would recommend changing about your code:
Don't use mysql_real_escape_string() if you're using mysqli. You can't mix these APIs.
No need to escape a string returned by md5(), because it's guaranteed to contain only hexadecimal digits.
Don't use mysqli_real_escape_string() anyway -- use parameters instead.
Always check if prepare() or execute() return false; if they do, then report the errors and exit.
You can get a mysqli result from a prepared statement using mysqli_stmt_store_result().
Don't SELECT * if you don't need all the columns. In this case, you already have $username so all you really need to fetch is the id column.
No need to check the number of rows returned, just start a loop fetching the rows (if any). Since you exit inside the loop, your "else" error clause will be output only if the loop fetches zero rows.
Consider using a stronger password hashing function than MD5. Also, add a salt to the password before hashing. Read You're Probably Storing Passwords Incorrectly.
Example:
<?php
if(isset($_POST['submit'])) {
$username = $_POST['username'];
$password = md5($_POST['password']);
$userControl = "SELECT id FROM users WHERE username=? AND password=?";
if (($userControlStmt = $mysqli->prepare($userControl)) === false) {
trigger_error($mysqli->error, E_USER_ERROR);
die();
}
$userControlStmt->bind_param("ss", $username, $password);
if ($userControlStmt->execute() === false) {
trigger_error($userControlStmt->error, E_USER_ERROR);
die();
}
$userControlResult = $userControlStmt->store_result();
while($userRow = $userControlResult->fetch_assoc()) {
$_SESSION['userid'] = $userRow["id"];
$_SESSION['username'] = $username;
header("location: me.php");
die();
}
// this line will be reached only if the while loops over zero rows
echo "<div class='errorField'>Användarnamnet eller lösenordet är fel!</div>";
}
?>
A good command to enter at the top of the script (under the
ini_set('display_errors', 1);
This will display any errors on your script without needing to update the php.ini (in many cases). If you try this, and need more help, please post the error message here and I'll be able to help more.
Also, if you are using $_SESSION, you should have
session_start();
at the top of the script under the
Make sure your php is set to show errors in the php.ini file. You'll need to do some research on this on your own, but it's fairly easy to do. That way, you'll be able to see what the error is and go from there.
I'm creating an e-commerce website. I am working on an admin page that lets the "store manager" log in to do things like add or remove products. In my database, I created a table called admin, with these fields:
id
password
time_last_logged_in
I inserted a row for my store manager, I can see the username and password so I know the person exists in the database, but when I try to log in it echoes out the error below.
admin_login.php
<?php
session_start();
if (isset($_SESSION["manager"])) {
header("location: index.php");
exit();
}
?>
<?php
if (isset($_POST["username"]) && isset($_POST["password"])) {
$manager = preg_replace('#[^A-Za-z0-9]#i', '', $_POST["username"]); // filter everything but numbers and letters
$password = preg_replace('#[^A-Za-z0-9]#i', '', $_POST["password"]); // filter everything but numbers and letters
// Connect to the MySQL database
include "../scripts/connect_to_mysql.php";
$sql = mysql_query("SELECT id FROM admin WHERE username='$manager' AND password='$password' LIMIT 1"); // query the person
// ------- MAKE SURE PERSON EXISTS IN DATABASE ---------
$existCount = mysql_num_rows($sql); // count the row nums
if ($existCount == 1) { // evaluate the count
while($row = mysql_fetch_array($sql)){
$id = $row["id"];
}
$_SESSION["id"] = $id;
$_SESSION["manager"] = $manager;
$_SESSION["password"] = $password;
header("location: index.php");
exit();
} else {
**echo 'That information is incorrect, try again Click Here';**
exit();
}
}
?>
I use a connect_test.php script to verify that it's connecting to the database and that there's no problem connecting.
index.php
<?php
session_start();
if (!isset($_SESSION["manager"])) {
header("location: admin_login.php");
exit();
}
// Be sure to check that this manager SESSION value is in fact in the database
$managerID = preg_replace('#[^0-9]#i', '', $_SESSION["id"]); // filter everything but numbers and letters
$manager = preg_replace('#[^A-Za-z0-9]#i', '', $_SESSION["manager"]); // filter everything but numbers and letters
$password = preg_replace('#[^A-Za-z0-9]#i', '', $_SESSION["password"]); // filter everything but numbers and letters
// Run mySQL query to be sure that this person is an admin and that their password session var equals the database information
// Connect to the MySQL database
include "../scripts/connect_to_mysql.php";
$sql = mysql_query("SELECT * FROM admin WHERE id='$managerID' AND username='$manager' AND password='$password' LIMIT 1"); // query the person
// ------- MAKE SURE PERSON EXISTS IN DATABASE ---------
$existCount = mysql_num_rows($sql); // count the row nums
if ($existCount == 0) { // evaluate the count
echo "Your login session data is not on record in the database.";
exit();
}
?>
Why might my code return That information is incorrect, try again Click Here'; instead of a successful validation?
The Problem(s?)
The way I see it, there are several problems with your code. I'll try to address each one and tell you how to solve each issue.
Issue #1: You are using REGEX To strip your code.
There are much better alternatives, the best of which is prepared statements which you should obviously use. Sadly, mysql_* functions don't support it. Which get's me to the next issue:
Issue #2: You are using mysql_* functions.
You shouldn't be using functions like mysql_query() and mysql_num_rows(), instead, consider moving to a better and more secure alternative, such as MySQLi (Good) or PDO (Awesome).
Issue #2.5: You are not using prepared statements.
A Prepared statement is automatically escaped and any malicious code or characters is render useless, same goes for SQL injections. You should use a better database handler that supports it (See Issue #2).
Issue #3: You are testing specifically.
You seem to test only if the row count is equal to exactly one. But what if there are (by accident) 2? Instead of testing what should be, test for what should not be:
if ($existCount != 0) { ...
Issue #4: You are not selecting the correct fields.
You only select the id field in your query, where instead you should be selecting all of the relevant fields (like username and password), in order to receive information.
Issue #5: You are not using secure storing.
If someone were to steal your database, they would have easy access to all your passwords. Consider using an encrypting method like sha1().
Issue #6: You are not testing for errors.
Errors can and will occur, you should test for them, with mysql_query() you should probably do something like
mysql_query("SELECT....") or die(mysql_error());
In PDO that would be something like
if (!$stmt->execute()) { throw new Exception("Execution failed.` . var_export($stmt->errorInfo(), true)); }
Try to correct those, and tell us if your problem persists.
Good luck :)
Try doing:
$sql = mysql_query("SELECT ... LIMIT 1") or die(mysql_error());
Your code assumes the query succeeds, which is very bad form. Always check for error conditions. You may have failed to connect to the database. perhaps your DB is malformed and you've got 2 or more records with the same username/password combo, etc...
I'm new to PHP myself, but I noticed that your select statement in the first code sample above selects only the id. That might be the problem. You should change it to select * and see if that makes any difference.
Good luck