I am trying to change a email confirmation function written in sql to PDO. This is the tutorial for your further reference: http://www.phpeasystep.com/phptu/24.html.
This particular section will move the user's information from the temporary table to the permanent table after they click on the verification link sent to their email.
The problem I am having is under this header within that tutorial: STEP4: confirmation.php
My code is similar to that, but I added a few prepared statements as I am trying to prevent SQL injection.
To be clear: I am looking for direction on what else I need to do to switch this from sql to PDO and prevent any sql injection. Examples when providing an answer are crucial as I am a visual learner. Thank you.
Here is my code:
<?php
include('config.php');
//Test DB connection
try {
$conn = new PDO("mysql:host=$Host;db=$svrDb", Username, $Password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo 'ERROR: ', $e->getMessage(), "\n";
}
// Passkey that got from link
$passkey=$_GET['passkey'];
$sql1= $conn->prepare("SELECT * FROM temp_members_db WHERE confirm_code ='$passkey'");
$sql_conf1->execute() or die ('Error updating database: '.mysql_error());
$result1=$sql1->fetchall();
// If successfully queried
if($result1){
// Count how many row has this passkey
$count=mysql_num_rows($result1);
// if found this passkey in our database, retrieve data from table "temp_members_db"
if($count==1){
$name=$rows['name'];
$email=$rows['email'];
$password=$rows['password'];
$country=$rows['country'];
// Insert data that retrieves from "temp_members_db" into table "registered_members"
$sql2="INSERT INTO registered_members(name, email, password, country)VALUES('$name', '$email', '$password', '$country')";
$result2=mysql_query($sql2);
}
// if not found passkey, display message "Wrong Confirmation code"
else {
echo "Wrong Confirmation code";
}
// if successfully moved data from table"temp_members_db" to table "registered_members" displays message "Your account has been activated" and don't forget to delete confirmation code from table "temp_members_db"
if($result2){
echo "Your account has been activated";
// Delete information of this user from table "temp_members_db" that has this passkey
$sql3="DELETE FROM temp_members_db WHERE confirm_code = '$passkey'";
$result3=mysql_query($sql3);
}
}
?>
Ok, so you're on the right track but not quite....
The whole reason you use Prepared Statements is so that the database knows what to interpret as SQL, and what not to interpret as SQL. Right now, you have the following:
$sql1= $conn->prepare("SELECT * FROM temp_members_db WHERE confirm_code ='$passkey'");
$sql_conf1->execute() or die ('Error updating database: '.mysql_error());
$result1=$sql1->fetchall();
To take full advantage of PDO and Prepared Statements you should change it to something like this:
$sql1= $conn->prepare("SELECT * FROM temp_members_db WHERE confirm_code = ?");
try{
$sql1->execute(array($passkey));
}catch(PDOException $e){
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
$result1=$sql1->fetchall();
There are a couple reasons for this. In your code, you send the variable $passkey along with your prepare statement, so in essence the prepare operation is useless because $passkey has not been sanitized. Notice in my code I replaced it with a ?. This tells the database:
"Hey, I'm going to be executing a SELECT statement and I'm going to replace the ? with a value from one of my variables, so don't interpret that as SQL!"
Here is a great resource for PDO:
http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers
Related
I have a Registration Form, but there are a few problems. This is my first registration form. Where the data is needed for data collection needs.
But when someone registers, a lot of duplicate data is in PHPMyAdmin. I've tried various ways, but you know, I'm just a student. I want to prevent duplicate email data.
<?php
$link = mysqli_connect("localhost", "xxxx", "", "db");
// Check connection
if($link === false){
die("ERROR: Could not connect. " . mysqli_connect_error());
}
// Escape user inputs for security
$nama = mysqli_real_escape_string($link, $_REQUEST['nama']);
$nohp = mysqli_real_escape_string($link, $_REQUEST['nohp']);
$email = mysqli_real_escape_string($link, $_REQUEST['email']);
$instagram = mysqli_real_escape_string($link, $_REQUEST['instagram']);
$sql = "INSERT INTO event (nama, nohp, email, instagram) VALUES ('$nama', '$nohp', '$email', '$instagram')";
if(mysqli_query($link, $sql)){
echo "<p class='text-center'>Pendaftaran Berhasil. Akan kembali ke halaman utama dalam 5 detik.<br/>
Atau klik <a href='index.php'>HOME</a></p>";
} else{
echo "ERROR: Could not able to execute $sql. " . mysqli_error($link);
}
// close connection
mysqli_close($link);
?>
What code do I need to add in it, so that someone who has registered their email will not be able to register again?
Sorry for my bad english
Add a unique constraint on the column you wish to be unique, then insert the data without any regard for duplication - MySQL will return an error if the value was duplicate, so all you need to do is catch the error.
First, make the field on that table a unique value (you can not have duplicate values on the table when doing this - if you have duplicate values in the event table, you must fix that first).
ALTER TABLE event
ADD UNIQUE (email);
Then we simply try to insert the data (using a prepared statement instead of escaping), and catch the error - and check for the error-code which belongs to unique constraint errors.
// Enable MySQLi exceptions
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
// Connect to the database
$link = new mysqli("localhost", "xxxx", "", "db");
// Attempt to insert the data
$sql = "INSERT INTO event (nama, nohp, email, instagram) VALUES (?, ?, ?, ?)");
$stmt = $link->prepare($sql);
$stmt->bind_param("ssss", $_REQUEST['nama'], $_REQUEST['nohp'], $_REQUEST['email'], $_REQUEST['instagram']);
$stmt->execute();
$stmt->close();
} catch (Exception $e) {
if ($e->getCode() == 1062) { // 1062 = Unique constraint error code
// Unique field error, handle it
// If you only have unique on the email, example:
// echo 'The email already exists';
} else {
// Handle the error, something else went wrong
error_log($e->getMessage());
echo "An unexpected error occurred";
}
}
You can add a UNIQUE constraint to the email field. This will be done by running the following query:
ALTER TABLE `event` ADD UNIQUE (email);
After that, when you want to insert a new row with an email that already exists in your table, you'll get an error like this: #1062 - Duplicate entry ...
You can catch that exception and react on it in your PHP code like this:
<?php
// perform INSERT query...
if (mysqli_errno($link) == 1062) {
print 'An error occured';
}
Put a unique constraint on email field directly onto table column. This will save you from duplicates (either inserted by your software or in other ways).
After that, you can check explictly via PHP script if the email is already there (but this will cost you an extra query and so is a no-go; moreover as Qirel correctly pointed out, this will expose you to potential concurrency issues) or try to insert and check insertion result (correct and safer way).
You can give emailID unique constraint, whenever the user submits form with a emailID that already exists in the table, MYSQL will throw an exception which you will need to catch and display the error message.
Reference :https://www.w3schools.com/php/php_exception.asp
I am trying to build an override feature so users can manually remove a MySQL table row if they have the correct rights to do so. The user is prompted to input the same credentials used for program login as well as the uniqueID for the row that needs to be removed. Upon hitting the 'Submit' function, I run a series of if statements/ MySQL SELECT statements to check credentials, user rights and finally row Deletion with the result output as an alert.
However, my alert shows up blank and the row is not removed so I know there is a problem with my if statements. Upon testing, I believe the problem is when I try to use the previous query's results to run the next if statement logic.
How do I properly determine if the MySQL query returned a row using prepared statements?
All help is appreciated! Thank you!
My CODE:
if ((isset($_POST['overrideUsername'])) and (isset($_POST['overridePassword'])) and (isset($_POST['overrideUniqueID']))) {
$overridePasswordInput = $_POST['overridePassword'];
$overrideUsername = $_POST['overrideUsername'];
$overridePassword = ENCODE(($overridePasswordInput).(ENCRYPTION_SEED));
$roleID = '154';
$overrideUniqueID = $_POST['overrideUniqueID'];
//connect to the database
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if(mysqli_connect_errno() ) {
printf('Could not connect: ' . mysqli_connect_error());
exit();
}
$conn->select_db($dbname);
if(! $conn->select_db($dbname) ) {
echo 'Could not select database. '.'<BR>';
}
$sql1 = "SELECT users.id FROM users WHERE (users.login = ?) AND (users.password = ?)";
$stmt1 = $conn->prepare($sql1);
$stmt1->bind_param('ss', $overrideUsername, $overridePassword);
$stmt1->execute();
$stmt1->bind_result($userID);
//$result1 = $stmt1->get_result();
if ($stmt1->fetch()) {
$sql2 = "SELECT * FROM rolestousers WHERE (rolestousers.userid = ?) AND (rolestousers.roleid = ?)";
$stmt2 = $conn->prepare($sql2);
$stmt2->bind_param('ss', $userID, $roleID);
$stmt2->execute();
$stmt2->store_result();
if ($stmt2->fetch()) {
$sql3 = "DELETE * FROM locator_time_track_out WHERE locator_time_track_out.uniqueid = ?";
$stmt3 = $conn->prepare($sql2);
$stmt3->bind_param('s', $overrideUniqueID);
$stmt3->execute();
$stmt3->store_result();
if ($stmt3->fetch()) {
echo 'Override Successful! Please scan the unit again to close it out.';
} else {
echo 'Could Not Delete Record from the table.';
}//End $sql3 if.
} else {
echo 'User does not have override permission. Please contact the IT Department.';
}//End $sql2 if.
} else {
echo 'Your login information is incorrect. Please try again. If the issue persists, contact the IT Department.';
}//End $sql1 if.
//Free the result variable.
$stmt1->free();
$stmt2->free();
$stmt3->free();
$stmt1->close();
//Close the Database connection.
$conn->close();
}//End If statement
NOTE: I am definitely sure my DB connection information is correct. The issue resides after I connect into the database. I have also tested the code using only the first if statement and get the blank alert so I'm not making it past the first if statement.
EDIT:: My php Script was definitely failing, but even earlier than expected, at the following code:
$overridePassword = ENCODE(($overridePasswordInput).(ENCRYPTION_SEED));
So my issue is that I need to properly compare the password and encryption seed information. However, the previous programmer used the following line to do the same process (which is obviously unsafe):
$querystatement = "SELECT id, firstname, lastname, email, phone, department, employeenumber, admin, usertype FROM users WHERE login=\"".mysql_real_escape_string($user)."\" AND password=ENCODE(\"".mysql_real_escape_string($pass)."\",\"".mysql_real_escape_string(ENCRYPTION_SEED)."\")";
$queryresult = $this->db->query($querystatement);
I will need to fix this issue before I can even test the functionality of the if logic using prepared statements.
Your are passing wrong variable for delete query
$stmt3 = $conn->prepare($sql3);
Please refer [ http://www.plus2net.com/php_tutorial/pdo-delete.php ]
I'm having the problem of mySQL not recognizing the session user when I select data from a table. Can someone please point me in the correct position on what I need to do to fix this?
$sql1="SELECT * FROM `Bookings` WHERE `username`={$_SESSION['user']}";
This is what my code looks like, but it never fetches the data and just remains blank.
First you should check if $_SESSION['user'] is initialized or has any value.
Second, it is better to assign the session user to a variable, so as to avoid some ugly issues related to escaping quotes, in the future. Don't just directly dump your session within your mysql statement.
$user_session = $_SESSION['user'];
$sql1="SELECT * FROM `Bookings` WHERE `username`= $user_session";
#Edit:
as #Dann pointed out, it's must better and safer to user prepared statement, with either the mysqli/pdo API. Here is a simple example in PDO.
First you have to connect to your database:
try {
$db = new \PDO("mysql:host=localhost;dbname=xx;charset=utf8", "xx", "xx", [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
} catch(\PDOException $e){
echo "Error connecting to mysql: ". $e->getMessage();
}
Then simply fetch the booking as seen below.
$user_session = $_SESSION['user'];
try{
$stmt = $db->prepare("SELECT * FROM Bookings WHERE username = ?");
$result = $stmt->execute([$user_session]);
if($result){
// show booking
}
} catch(\PDOException $e){
echo "Counld not get user bookings. error: " . $e->getMessage();
}
Now your query is safer from mysql injection attacks, and connection errors will only throw exceptions, instead of showing potentially harmful errors.
You can use
$user=$_SESSION['user'];
$sql1="SELECT * FROM Bookings WHERE username= '$user'";
Hopefully This will solve your problem
I'm trying to check if a user exists on the database using a form front end.
If the user is there don't add to the database.
The code isn't working when adding a user it gives me the user has been added even the user exists.
Here my code:
<?php
$connection = mysql_connect("localhost", "dbuser", "dbpasswd"); // Establishing Connection with Server
$db = mysql_select_db("ldap", $connection); // Selecting Database from Server
if(isset($_POST['submit'])){ // Fetching variables of the form which travels in URL
$netid = $_POST['netid'];
$univid = $_POST['univid'];
if($netid !=''||$univid !=''){
//Insert Query of SQL
$query = mysql_query("SELECT FROM user ( UserName, temppass WHERE UserName=$netid");
if(mysql_num_rows($sql)>=1)
{
echo"NetID $netid already exists";
}
else
{
//insert query goes here
$query = mysql_query("insert into user( UserName, temppass ) values ('$netid', '$univid')");
}
echo "<br/><br/><span>User Registered successfully...!!</span>";
}
else{
echo "<p>Registration Failed <br/> Some Fields are Blank....!!</p>";
}
}
mysql_close($connection); // Closing Connection with Server
?>
You could do something like:
$query = mysql_query("SELECT COUNT(UserName) as total FROM user;");
Then
$result = mysql_fetch_assoc($query);
The count of users will be in $result['total']. As an aside the mysql_* methods are inferior to prepared statements (google it).
Your select query has many errors with it.
SELECT FROM user ( UserName, temppass WHERE UserName=$netid
First issue you aren't selecting anything. Second issue I don't know what ( UserName, temppass is, maybe the columns you want to select? Third issue is that Username is presumably a string, not an integer, so that value should be in quotes. Once you quote that though you will open yourself to SQL injections.
Here is a valid version of your current query.
SELECT UserName, temppass FROM user WHERE UserName='$netid'
Here's the doc on mysql's select: http://dev.mysql.com/doc/refman/5.7/en/select.html
Here are some links to read up on about SQL injections:
How can I prevent SQL injection in PHP?http://php.net/manual/en/security.database.sql-injection.php
You also shouldn't be using the mysql_ functions they are deprecated and insecure now. Why shouldn't I use mysql_* functions in PHP?
Additional issues:
if(mysql_num_rows($sql)>=1)
The $sql isn't defined.
I don't know what $_POST['netid'] is but that sounds like an id, not a username.
You shouldn't store passwords in plain text.
You should enable error reporting and/or monitor your error logs.
so I have a simple newsletter signup form. I can add users into the database, but I want to account for duplicate emails. This is what I have right now.
$result = mysql_query("SELECT * FROM Users WHERE Email='$email'");
$num_rows = mysql_num_rows($result);
if($num_rows){
echo "You've already registered! Thanks anyway";
}
else{
mysqli_query($db_connection, "INSERT INTO Users (Name, Email) VALUES('$name' , '$email')");
echo "Thanks for signing up, $name.";
}
When I click submit, it will add it to the database, regardless if the email is the same.
The mysql_query that gets $result is fine. However, for some reason the if statement doesn't get called. Any idea why?
"The mysql_query that gets $result is fine"
Your DB connection sounds to be mysql_ - and you're using mysqli_ functions below that.
Use mysqli_ exclusively and do not mix them, they don't.
Sidenote: Your question is confusing.
You state: When I click submit, it will add it to the database, regardless if the email is the same. - then you say The mysql_query that gets $result is fine.
This: if($num_rows) should be if($num_rows >0)
Use this for your DB connection:
$db_connection = mysqli_connect("your_host","user","password","your_db");
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
then do:
$result = mysqli_query($db_connection, "SELECT * FROM Users WHERE Email='$email'");
$num_rows = mysqli_num_rows($result);
if($num_rows >0){
echo "You've already registered! Thanks anyway";
exit;
}
else{
mysqli_query($db_connection, "INSERT INTO Users (Name, Email) VALUES('$name' , '$email')");
echo "Thanks for signing up, $name.";
}
Use http://php.net/manual/en/mysqli.error.php on your query.
I.e.: or die(mysqli_error($db_connection))
Warning
Your present code is open to SQL injection.
Use prepared statements, or PDO with prepared statements.
Footnotes:
If you want to avoid duplicates, set your column(s) as UNIQUE.