I'm trying to create a sign up page for a website using PHP and PHPMyAdmin.
I have set 2 fields in the form needed for registration: email and password, with password confirmation.
Both of them are treated as string in PHP and as varchar in database. I don't know why, but everytime the user insert email and password and confirm, the new user is being inserted in database, but with email and password as 0 insted their real value. I'm sure that email and password values inside the PHP variables are correct, because i printed to output their content immediatly before the mysqli query, so i'm assuming that is a database problem.
I'm currently using Wamp Server for Windows 8 and PHPMyAdmin 4.1.14. Database is of type InnoDB and with latin_swedish_ci characters.
The query used in PHP is:
"INSERT INTO users (email,password) VALUES (email = '$email', password = '$password')"
using mysqli_query for the execution.
Instead of doing column equals variable, do:
VALUES ('$email','$password')
if an INSERT is indeed what you wish to use.
that syntax VALUES (email = '$email', password = '$password') is for when you want to check if a column equals something, when using a WHERE clause for example.
WHERE email = '$email'
or
WHERE email = '$email' AND password = '$password'
when doing an UPDATE as another example:
UPDATE table_name SET email = '$email', password = '$password'
WHERE column_x='something'
or, when doing a SELECT as another example:
SELECT * FROM table_name
WHERE column_x = 'something' OR column_y = 'something else'
Sidenote: OR can be replaced by AND, depending on the desired query.
Yet, when you do fix it, that present method is open to SQL injection. Use prepared statements, or PDO with prepared statements, they're much safer.
Look into those, you will be glad you did.
A basic example to prevent SQL injection is:
$email = mysqli_real_escape_string($con, $_POST['email']);
$password = mysqli_real_escape_string($con, $_POST['password']);
Error checking sidenote:
Add error reporting to the top of your file(s) which will help during production testing.
error_reporting(E_ALL);
ini_set('display_errors', 1);
and or die(mysqli_error($con)) to mysqli_query() while replacing $con with your DB connection variable.
Matteo - also, you should consider parameterizing your php syntax to prevent SQL injections. Better to do it now than to have to come back to it later. You can find an explanation of the concepts here; https://stackoverflow.com/questions/25316766/understanding-parameterized-queries-and-their-usage-in-preventing-sql-injections
INSERT INTO users (email,password) VALUES ('$email', '$password')
you don't need column name after VALUES. You have already specified it after table name.
By the way, you may want to look at php prepared statement
Related
I have a table called user_bio. I have manually entered one row for username conor:
id: 1
age: 30
studying: Business
language: English
relationship_status: Single
username: conor
about_me: This is conor's bio.
A bio is unique to a user, and obviously, a user cannot manually set their bio from inserting it in the database. Consider the following scenario's:
Logged in as Conor. Since Conor already has a row in the database, I simply want to run an UPDATE query to update the field where username is equal to conor.
Logged in as Alice. Since Alice has no row in the database corresponding to her username. Then I want to run an INSERT query. For all users, all users will have to have their details inputted, and then updated correspondingly.
At the moment, I am struggling with inserting data in the database when no rows exist in the database.
Here is my current approach:
$about_me = htmlentities(trim(strip_tags(#$_POST['biotextarea'])));
$new_studying = htmlentities(trim(strip_tags(#$_POST['studying'])));
$new_lang = htmlentities(trim(strip_tags(#$_POST['lang'])));
$new_rel = htmlentities(strip_tags(#$_POST['rel']));
if(isset($_POST['update_data'])){
// need to check if the username has data already in the db, if so, then we update the data, otherwise we insert data.
$get_bio = mysqli_query($connect, "SELECT * FROM user_bio WHERE username ='$username'");
$row_returned = mysqli_num_rows($get_bio);
$get_row = mysqli_fetch_assoc ($get_bio);
$u_name = $get_row['username'];
if ($u_name == $username){
$update_details_query = mysqli_query ($connect, "UPDATE user_bio SET studying ='$new_studying', language ='$new_lang',
relationship_status = '$new_rel', about_me = '$about_me' WHERE username ='$username'");
echo " <div class='details_updated'>
<p> Details updated successfully! </p>
</div>";
} else {
$insert_query = mysqli_query ($connect, "INSERT INTO user_bio
VALUES ('', '$age','$new_studying','$new_lang','$new_rel', '$username', '$about_me'");
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
echo " <div class='details_updated'>
<p> Details added successfully! $row_returned </p>
</div>";
}
}
The UPDATE query works fine, when logged in as Conor. But again, INSERT does not work when logged in as Alice.
MySQL support INSERT ... ON DUPLICATE KEY UPDATE type of queries. So you do not need to make few queries to check existance of row in your php code, just add corrct indexes and let your DB take care about this.
You can read about such type of queries here
Here are a few things you could do to make it work:
Prevent SQL injection
As this is an important issue, and the suggested corrections provided below depend on this point, I mention it as the first issue to fix:
You should use prepared statements instead of injecting user-provided data directly in SQL, as this makes your application vulnerable for SQL injection. Any dynamic arguments can be passed to the SQL engine aside from the SQL string, so that there is no injection happening.
Reduce the number of queries
You do not need to first query whether the user has already a bio record. You can perform the update immediately and then count the records that have been updated. If none, you can then issue the insert statement.
With the INSERT ... ON DUPLICATE KEY UPDATE Syntax, you could further reduce the remaining two queries to one. It would look like this (prepared):
INSERT INTO user_bio(age, studying, language,
relationship_status, username, about_me)
VALUES (?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY
UPDATE studying = VALUES(studying),
language = VALUES(language),
relationship_status = VALUES(relationship_status),
about_me = VALUES(about_me);
This works only if you have a unique key constraint on username (which you should have).
With this statement you'll benefit from having the data modification executed in one transaction.
Also take note of some considerations listed in the above mentioned documentation.
NB: As in comments you indicated that you prefer not to go with the ON DUPLICATE KEY UPDATE syntax, I will not use it in the suggested code below, but use the 2-query option. Still, I would suggest you give the ON DUPLICATE KEY UPDATE construct a go. The benefits are non-negligible.
Specify the columns you insert
Your INSERT statement might have failed because of:
the (empty) string value you provided for what might be an AUTO_INCREMENT key, in which case you get an error like:
Incorrect integer value: '' for column 'id'
a missing column value, i.e. when there are more columns in the table than that you provided values for.
It is anyway better to specify explicitly the list of columns in an INSERT statement, and to not include the auto incremented column, like this:
INSERT INTO user_bio(age, studying, language,
relationship_status, username, about_me)
VALUES (?, ?, ?, ?, ?, ?)
Make sure you get notified about errors
You might also have missed the above (or other) error, as you set your error reporting options only after having executed your queries. So execute that line before doing any query:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
And also add there:
error_reporting(E_ALL);
ini_set('display_errors', 1);
In a production environment you should probably pay some more attention to solid error reporting, as you don't want to reveal technical information in the client in such an environment. But during development you should make sure that (unexpected) errors do not go unnoticed.
Do not store HTML entities in the database
It would be better not to store HTML entities in your database. They are specific to HTML, which your database should be independent of.
Instead, insert these entities (if needed) upon retrieval of the data.
In the below code, I removed the calls to htmlentities, but you should then add them in code where you SELECT and display these values.
Separate view from model
This is a topic on its own, but you should avoid echo statements that are inter-weaved with your database access code. Putting status in variables instead of displaying them on the spot might be a first step in the right direction.
Suggested code
Here is some (untested) code which implements most of the above mentioned issues.
// Calls to htmlentities removed:
$about_me = trim(strip_tags(#$_POST['biotextarea']));
$new_studying = trim(strip_tags(#$_POST['studying']));
$new_lang = trim(strip_tags(#$_POST['lang']));
$new_rel = trim(strip_tags(#$_POST['rel']));
// Set the error reporting options at the start
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
if (isset($_POST['update_data'])) {
// Do not query for existence, but make the update immediately
$update_stmt = mysqli_prepare ($connect,
"UPDATE user_bio
SET studying = ?,
language = ?,
relationship_status = ?,
about_me = ?
WHERE username = ?");
mysqli_stmt_bind_param($update_stmt, "sssss",
$new_studying, $new_lang, $new_rel, $about_me, $username);
mysqli_stmt_execute($update_stmt);
$num_updated_rows = mysqli_stmt_affected_rows($update_stmt);
mysqli_stmt_close($update_stmt);
if ($num_updated_rows === 0) {
$insert_stmt = mysqli_prepare ($connect,
"INSERT INTO user_bio(age, studying, language,
relationship_status, username, about_me)
VALUES (?, ?, ?, ?, ?, ?)");
mysqli_stmt_bind_param($insert_stmt, "isssss",
$age, $new_studying, $new_lang, $new_rel, $username, $about_me);
mysqli_stmt_execute($insert_stmt);
mysqli_stmt_close($insert_stmt);
}
// Separate section for output
$result = $num_updated_rows ? "Details updated successfully!"
: "Details added successfully!";
echo " <div class='details_updated'><p>$result</p></div>";
}
Aside from security issues and bad coding practices, here are a couple things you can do.
You don't need to compare the name to check if the bio already exists. You can just count the number of rows returned. If it is more than zero, then the user bio already exists.
When comparing strings, === is preferred over ==. You can read about it and find out why but here is an example (2nd answer)
You should really look into either REPLACE INTO or ON DUPLICATE KEY UPDATE. Just using either of there 2, depending on your use case pick one, you can pretty much eliminate more than half of your currently displayed code. Basically, both will insert and if the record already exists, they updates. Thus, you wouldn't even need to check if the record already exists.
I have made a database where email id and corresponding name and password is stored. I have successfully obtained a form's data.. where the user enters updated name and password. But the problem is occuring with the query which is as follows
$db = mysqli_connect(all details)...
$name = $_POST['name'];
$password = $_POST['password']:
$email = $_POST['email'];
$query = "UPDATE mytable SET name='$name',password='$password' WHERE emailid='$email'";
$result = mysqli_query($db,$query);
Though I am getting all form values succesffuly and until and unless I put the 'where' clause.It works.But obviously updates all values. i want it to work with where..but so far unsuccessful :(
you need to put {} around the variables if its surrounded by quote ''
so your query should look like this
$query = "UPDATE mytable SET name='{$name}',password='{$password}' WHERE emailid='{$email}'";
$result = mysqli_query($db,$query);
EDIT : also before saving data to database make sure to filter and validate data
You need to make sure that emailid exists in mytable, you truly intended to filter by it and in your database scheme it has a type which supports the posted data. It seems that you are sending strings, like 'foo#bar.lorem' and your emailid is an int or something in the database scheme. Check it by running
desc mytable;
You need to put curly brackets around variables if you use apostrophe around them, but as a matter of style I like to close the string and attach the $variable with a . as this coding style is closer to me personally.
If everything fails, see what is generated, by echoing out the query string, try to run that directly, see what the error is and fix until...
... until it is fixed.
Also, you do not encrypt the password and your code is vulnerable to SQL injection too. Please, read about password encryption and SQL injection and then protect your project against these dangers.
You can write your statement as:
$query = "UPDATE mytable SET name='".$name."',password='".$password."' WHERE emailid='".$email."'";
using . as string concatenating operator
I am a newbie in PHP and i am trying to create a system where user will add firstname, lastname and email address. Basically what i am trying to do is verify if the e-mail already exists in database or not.
Have been working for hours but it doesn't work. But when i try to verify the firstname and lastname they both works.
But with email field ... the code cannot compare that there are duplicate values. There are lot of duplicate email Id in the database but the code ignores that and inserts the value :/. Meanwhile if i try verifying for duplicate firstname and lastname it works
Any help please :(
$firstname=$_POST['firstname'];
$lastname=$_POST['lastname'];
$email=$_POST['email'];
$firstname= stripslashes($firstname);
$lastname= stripslashes($lastname);
$email= stripslashes($email);
$host="localhost";
$user="root";
$pass="";
$db="site";
$link=mysql_connect($host,$user,$pass);
mysql_select_db($db,$link);
$test="SELECT * FROM email_list WHERE email = '$email' ";
$select=mysql_query($test);
if(mysql_num_rows($select)>0)
{
echo "Email already exists".$email."<br>";
echo "Please enter another email";
}
else
{
$query="INSERT into email_list (first_name, last_name, email) values ('$firstname', '$lastname', '$email')";
mysql_query($query);
echo "values entered" .$firstname. "<br>". $lastname. "<br>". $email;
}
First of all as you can read from the comments below your question mysql_* isn't recomended any longer. try mysqli_* functions instead if you like the procedural approach, but that is besides the point.
Your code as it is above seems without any obvious error but inserting raw input into a database is a dangerous thing - you should (at the minimum) change your INSERT and SELECT statemens so all the textual input is enclosed in mysql_real_escape_string() function.
The select statement would then look like this:
"SELECT * FROM email_list WHERE email = '".mysql_real_escape_string($email)."' ";
That will not change the behaviour of your code, it will only make sure, that if someone enters nonsense into $email field it will be saved as entered (without crashing your code) or if they try to "hack" (inject) your mysql queries they will not succeed in doing so.
I am guessing here from (as i do not have too much information to work with) that your email field in email_list table is too short - and saving only maybe first 16 characters of any entered email address - which in turn will not help you determining whether an email address exists because you are comparing the entered joe#test.com with joe#test.c (that in case if your email field was defined as char(10)
Basic debugging steps:
mysql_query() can fail. You don't test it. Test it:
$select=mysql_query($test);
if(!$select){
die(mysql_error());
}
If mysql_num_rows() is never greater than zero, you should find out what it is:
var_dump(mysql_num_rows($select));
This function does not work with all possible configurations.
You run a SELECT query? Aren't you curious about the result set? Grab and print all rows.
Additionally:
There's more SQL than SELECT * FROM table. If you want to count, you can count in SQL:
SELECT COUNT(*) AS dupes FROM email_list
You are using a MySQL extension that will be removed when the next major PHP release comes out.
I see stripslashes() out there. The magic quotes feature is annoying, useless and deprecated.
Make sure you read and understand How to prevent SQL injection in PHP?.
I strongly agree with the one who points out that mysql_query and mysql in general should be avoided (also because they're going to deprecate it sooner or later). You want to switch to MySQLi or whatever else. This said, you're not checking for errors. Does the connection to database fail? You'll never know. Does $test fail? You'll never know either.
Try to debug with an "or die()" (N.B.: or die(); is strongly discouraged! However, if its' not used in production it'll suffice it).
mysql_select_db($db,$link) or die("cannot open db");
$select=mysql_query($test) or die ("cannot select the email");
EDIT: to check if the email is in the database, you probably need a function to do that. Or, if you don't want to put it into a function, try to edit this way
$test="SELECT * FROM email_list WHERE email = '$email' ";
$select=mysql_query($test);
if(mysql_num_rows($select)!=0) //different from 0
{
echo "Email already exists".$email."<br>";
echo "Please enter another email";
}
I hope this helps.
Everything looks okay but Check your defined length of email on your db, if it matches the one you're sending then try and print the email being accepted on your form. Like
Print $email ;
And I'll advice you change all names of "mysql" to "mysqli"
I enclosed the '$email' variable in parentheses and it worked for me.
$test= "SELECT Password FROM persons WHERE Email=('$email')";
I've user profile update page and have some forms to update, here they are
NAME
SURNAME
password
phone
And I am trying to make this update without big script, I mean I don't want to define if for example NAME exists or not and so on. I want that if any marked form value exists it changed in mysql. How I know this is possible with mysqli_prepare statement. I've written sql like this
$stmt = "UPDATE table SET NAME=?,SURNAME=?,PASSWORD=?,PHONE=? WHERE email='" . $email . "'";
but something wrong, any ideas how to do it ? And also please advice why it is better way to use mysqli_prepare , why it is safe too ?
PS. I do not write php script because I've not any problem with it
UPDATE
I've marked sql statement and above this script in php I am writting this =>
if (isset($_POST['name']){
$name = $_POST['name'];
} else {
$name = null;
}
and so on ...
but it doesn't execute , nothing error msg is shown up , because I think something wrong with sql statement
Just want if some of detail is filled it updated and if all fields are filled all updated, how to write with script?
I can not understand this question marks in sql statement , does it means that if for example NAME is not exists it is ignored ?
The question marks in your SQL string not part of the SQL syntax, they are placeholders for the actual parameters. If you want to do it like this, you should first make a SQL statement, and then set the parameters.
Something like
$con = new mysqli($hostname,$username,$password,$database);
$statement = $con->prepare( "UPDATE table SET NAME=?,SURNAME=?,".
"`PASSWORD`=?,PHONE=? ".
" WHERE email=?");
$statement->bind_param("sssss",$name,$surname,$pass,$phone,$email);
example derived of http://www.xphp.info/security/getting-started-with-mysqli/
Also note the comment of ThiefMaster: password is a reserved word in MySQL so you will need to put it in backticks (``)
Alternatively you directly insert the values into the mysql string, like you initially did with the email address. You need to escape the values in that case, by using mysql_real_escape_string()
Note that you are in both cases replacing ALL values with what was set, be it NULL or a string, or whatever.
I have two problems.
problem one:
I am trying to create a registeration form where users can register with my website.
when I run this mysql statement a get dublicate entry found error:
$sql "insert into users(username, password) values('$username, sha('$password'))";
Duplicate entry 'da39a3ee5e6b4b0d3255bfef95601890afd80709' for key 'password'
despite the fact that I changed the the string sha('$password') several times.
please help.
else{
include("databaseconnection.php");
$databaseconnect = connect($host,$user,$password,$database)
or die("couldnot connect to database serever.\n");
$database_select = mysql_select_db($database,$databaseconnect)
or die("could not select dabases.\n " .mysql_error());
$query2 = "insert into company(username,password)
values('$username',sha1('$password'))";
$result2 = mysql_query($query2,$databaseconnect);
echo "you have been registered as '$companyloginName' <br/>";
header("Location:/index.php");
my login php script is as follow:
$result ="select username, password form users where username ='$username' and password = sha('$password');
if(mysql_num_rows($reuslt)==1){
echo"welcome '$username";
}
First, I would STRONGLY advice against using MySQL's sha() or PHP's sha1() alone for password hashing purposes. This is a huge security risk for your users if your database gets compromised.
Please take the time to read my previous answer on the subject of password hashing to properly secure your data.
Second, your code is vulnerable to an SQL Injection attack. Use mysql_real_escape_string() to escape the variables you are going to put in your query before-hand.
$query2 = "insert into company(username,password)
values('" . mysql_real_escape_string($username) .
"', sha1('" . mysql_real_escape_string($password) . "'))";
Third, your $password variable is being overwritten by your databaseconnection.php file.
include("databaseconnection.php");
$databaseconnect = connect($host,$user, $password ,$database);
To put emphasis...
$databaseconnect = connect($host,$user,$password,$database);
Therefore, the $password used later on in your query still contains the password for the database connection, not your user's password.
Change the name of your variable in databaseconnection.php or even better still, use an array to hold all the configuration.
$dbConnectParams = array('host' => 'localhost'
'user' => 'myUser',
'pass' => 'myPassword',
'db' => 'myDB');
Then, change your code as follows:
include("databaseconnection.php");
$databaseconnect = mysql_connect($dbConnectParams['host'],
$dbConnectParams['user'],
$dbConnectParams['pass'],
$dbConnectParams['db']);
Since you are already passing the database when calling mysql_connect(), you do no need to call mysql_select_db().
da39a3ee5e6b4b0d3255bfef95601890afd80709 is the sha1 hash of the empty string. Make sure that you actually insert the password into your SQL query, for example by echoing the query instead of sending it to the SQL server.
Edit With the new information added to your question, check out these two lines:
include("databaseconnection.php");
$databaseconnect = connect($host,$user,$password,$database)
Here, $password is the password used to connect to the database. The inclusion of databaseconnection.php probably overwrites what was previously in the $password variable.
Try to echo $query2 and you'll probably see it for yourself, that the SQL query doesn't include any password at all or that the password therein is not the same as the one entered by the user.
Guessing from the commented line, it may be possible you accidentally use the connection password that is set in 'databaseconnection.php' rather than the user password - you don't show how you initialize the $password string.
Also note the comma in your sql that shouldn't be there:
insert into company(username,password,)
^
I have not tested if that is the cause, but you should probably get rid of it and test it again.
Also, seriously consider pdo / prepared statements to prevent sql-injections, even more so if you want to insert the password from user input.