I'm a little confused about Prepared Statements in PHP, I've been watching the following tutorial on youtube: https://www.youtube.com/watch?v=aN5KqxK1slc
After I've received the following note on my currently Mysqli source code:
You are wide open to SQL Injections and should really use Prepared
Statements instead of concatenating your queries. Specially since
you're not escaping the user inputs at all!
My question:
How would I prepare the statement since I'm creating the syntax for the statement inside my register class and only pass the statement to my database class to execute it using the execute_query function?
Would I just prepare the statement inside the execute_query function and check if its either a statement of the format INSERT or SELECT and then prepare the values?
I appreciate any kind of suggestions and feedback.
My current code looks like the following:
Register class:
<?php
class register extends database
{
function __construct($username, $password, $email)
{
$this->username = $username;
$this->password = password_hash($password, PASSWORD_DEFAULT);
$this->email = $email;
$this->activation_id = $this->generateActivationId();
$this->sender_email = 'support#url.com';
$this->activation_link = 'http://url.com/folder/activate.php?id=' . $this->activation_id;
$this->database = new database();
}
function generateActivationId()
{
$generator = bin2hex(random_bytes(10));
return $generator;
}
function registerAccount()
{
$this->database->connect();
$user_lookup = $this->database->execute_query("SELECT * FROM users WHERE username = '" . $this->username . "'");
if (mysqli_num_rows($user_lookup) > 0)
{
return false;
}
else
{
$this->database->execute_query("INSERT INTO users (username, password, email, activation_id) VALUES ('" . $this->username . "', '" . $this->password . "', '" . $this->email . "', '" . $this->activation_id . "')");
$user_lookup_comfirm = $this->database->execute_query("SELECT * FROM users WHERE username = '" . $this->username . "'");
if (mysqli_num_rows($user_lookup_comfirm) > 0)
{
$this->sendRegisterEmail();
return true;
}
else
{
return false;
}
}
}
function sendRegisterEmail()
{
$subject = 'Registration - Activate your account';
$message = 'Thank you for registering. Please activate your account by visiting the following site: Website link';
$headers = 'From: ' . $this->sender_email . "\r\n" .
'Reply-To: ' . $this->sender_email . "\r\n" .
'X-Mailer: PHP/' . phpversion();
mail($this->email, $subject, $message, $headers);
}
}
?>
Database class:
<?php
class database
{
function __construct()
{
$this->dBusername = 'xxx';
$this->dBpassword = 'xxx';
$this->dBhost = 'localhost';
$this->dBdatabase = 'xxx';
$this->dBcharset = 'utf8';
}
function connect()
{
$mysqli = new mysqli($this->dBhost, $this->dBusername, $this->dBpassword, $this->dBdatabase);
if ($mysqli->connect_errno)
{
$this->_mysqli = false;
}
else
{
$mysqli->set_charset($this->charset);
$this->_mysqli = $mysqli;
}
}
function execute_query($sql)
{
if($results = $this->_mysqli->query($sql))
{
return $results;
}
else
{
return false;
}
}
}
?>
<?php
class Config{
private function Db(){
$db = null;
$dsn = UR DSN;
$user = UR USER;
$pass = UR PASS;
try{
$db = $pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::ATTR_TIMEOUT => "10"));
return $db;
} catch(Exception $e){
var_dump($e);
}
return null;
}
function execPreparedStatement($sql , Array $param = null){
try{
$db = $this->Db();
if($db != null && ($db instanceof PDO)){
$db->beginTransaction();
$stm = $db->prepare($sql);
for ($i = 0 ; $i < count($param) ; $i++){
$stm->bindValue($i + 1,$param[$i]);
}
$dat = $stm->execute();
$db->commit();
$stm = null;
$db = null;
return $dat;
}
} catch (PDOException $e) {
$db->rollBack();
var_dump("<br><br>Error: ".$e->getMessage().' in '.$e->getFile().' on line '.$e->getLine(), $sql, $param);
}
}
function getPreparedStatement($sql , Array $param = null,$type = null) {
$db = $this->Db();
if($db != null && ($db instanceof PDO)) {
$stm = $db->prepare($sql);
if(!empty($param)){
for ($i = 0 ; $i < count($param) ; $i++){
$stm->bindParam($i+1, $param[$i]);
}
}
try {
$stm->execute();
if($type) {
$dat = #$stm->fetchAll(PDO::FETCH_ASSOC);
} else {
$dat = #$stm->fetchAll();
}
$stm = null;
$db = null;
return $dat;
} catch (Exception $e){
var_dump("<br><br>Error capturado: ".$e->getMessage().' in '.$e->getFile().' on line '.$e->getLine(),$sql,$param);
}
}
}
}
this is a PDO class u can use it as this
<?php
$db = new Config();
// This is for an update
$db->execPreparedStatement('update table set a = ?, b = ? where id = ?)', array(value1, value2, id));
// Select With out filter
$data = $db->getPreparedStatment('select * from table');
// With Filter.
$data = $db->getPreparedStatment('select * from table where id = ?', array(id));
this is just and example i can give u more feed back if u need. but i think with this u can do it on ur own
Related
Here is my code:
<?php
class Db
{
private $servername = 'localhost';
private $username = 'root';
private $password = '';
private $dbname = 'emp';
function __construct()
{
$this->db = new mysqli(
$this->servername,
$this->username,
$this->password,
$this->dbname
);
if ($this->db->connect_error) {
die("Connection failed: " . $this->db->connect_error);
}
}
public function insert_record($table, $fields)
{
$sql = "";
$sql .= "INSERT INTO " . $table;
$sql .= " (" . implode(",", array_keys($fields)) . ")values";
$sql .= " ('" . implode("','", array_values($fields)) . "')";
$query = mysqli_query($this->db, $sql);
if ($query) {
return true;
}
}
}
//making object of the class
$crudobj = new Db;
//insert code for adding data in to the db
if (isset($_POST['submit'])) {
$myArray = array(
"username" => $_POST["unm"],
"email" => $_POST["eid"],
"password" => $_POST["pass"]
);
//inserting data
if($crudobj->insert_record("users", $myArray))
{
header("location: login.pho")
}
}
?>
Call it with your input email.
if($crudobj->is_email_exists($_POST["eid"]))
{
echo "Email Already Exist";
}
Add below function in your DB class:
public function is_email_exists($email)
{
if(filter_var($email, FILTER_VALIDATE_EMAIL))
{
$email = mysqli_real_escape_string($this->db, $email);;
$sql = "SELECT email FROM users WHERE email='".$email."';";
if($result = mysqli_query($this->db, $sql))
{
return mysqli_num_rows($result);
}
}
return true;
}
I have the following code
<?php
$host = "localhost";
$dbname = "hawkI";
$user = "root";
$password = "";
$userExist = false;
$userIP = null;
$userHasFinish = null;
$userLastPage = null;
try {
$dbh = new PDO('mysql:host='.$host.';dbname='.$dbname, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
function getIPforBDD(){
return $_SERVER['REMOTE_ADDR'];
}
function UpdateUserProfile()
{
$requete = "SELECT * FROM users WHERE ip = ".getIPforBDD();
$result = $dbh->query($requete);
if($resultat->rowCount() == 0)
exit();
foreach($result as $ligne)
{
$userIP = $ligne['ip'];
$userhasFinish = $ligne['finish'];
$userLastPage = $ligne['lastPage'];
}
}
function CheckUserPosition()
{
UpdateUserProfile();
if(!$userExist)
AddUser();
return GetUserStatus();
}
function GetUserStatus()
{
$page;
if($userHasFinish)
$page = "end.php";
else
$page = $userLastPage;
return $page;
}
function AddUser()
{
$requete = "INSERT INTO users (ip, finish, lastPage) VALUES (".getIPforBDD().", ".false.", questionnaire_initial.php)";
$result = $dbh->query($requete);
}
function SavePageInBDD($page){
$requete = "UPDATE users SET lastPage = '.$page.' WHERE ip = ".getIPforBDD();
$result = $dbh->query($requete);
}
?>
But, I have a problem when I use it
( ! ) Notice: Undefined variable: dbh in C:\wamp64\www\HawkI\bdd.php
on line 66
I do not understand correctly how PHP work it's the first time I use it, but I tried to make
global $dbh = new PDO('mysql:host='.$host.';dbname='.$dbname, $user, $password);
That doesn't work too.
Also, it seems that value that are put outside of functions are not global like it would be in js, how can I make something accessible from everywhere (like file that include that file)
Thanks
Better way would be to do something like this:
function getDB(){
$dbh = null;
try {
$dbh = new PDO('mysql:host='.$host.';dbname='.$dbname, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
return $dbh;
}
And than in your functions do this:
function AddUser()
{
$dbh = getDB();
if(!is_null($dbh)){
$requete = "INSERT INTO users (ip, finish, lastPage) VALUES (".getIPforBDD().", ".false.", questionnaire_initial.php)";
$result = $dbh->query($requete);
}
}
To use $dbh inside a function, you need to include global keyword inside the function scope.
You can find the global keyword explanation here http://php.net/manual/en/language.variables.scope.php#language.variables.scope.global
function AddUser()
{
global $dbh;
$requete = "INSERT INTO users (ip, finish, lastPage) VALUES (".getIPforBDD().", ".false.", questionnaire_initial.php)";
$result = $dbh->query($requete);
}
You may use like this
$host = "localhost";
$dbname = "hawkI";
$user = "root";
$password = "";
$userExist = false;
$userIP = null;
$userHasFinish = null;
$userLastPage = null;
$dbh = NULL;
function db () {
try {
if ($GLOBALS['dbh']===NULL){
$GLOBALS['dbh'] = new PDO('mysql:host='.$host.';dbname='.$dbname, $user, $password);
}
return $GLOBALS['dbh'];
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
function SavePageInBDD($page){
$dbh = db();
$requete = "UPDATE users SET lastPage = '.$page.' WHERE ip = ".getIPforBDD();
$result = $dbh->query($requete);
}
below is my MySQLDao.php
<?php
class MySQLDao {
var $dbhost = null;
var $dbuser = null;
var $dbpass = null;
var $conn = null;
var $dbname = null;
var $result = null;
function __construct() {
$this->dbhost = Conn::$dbhost;
$this->dbuser = Conn::$dbuser;
$this->dbpass = Conn::$dbpass;
$this->dbname = Conn::$dbname;
}
// function to open connection
public function openConnection() {
$this->conn = new mysqli($this->dbhost, $this->dbuser, $this->dbpass, $this->dbname);
if (mysqli_connect_errno())
echo new Exception("Could not establish connection with database");
}
// function to return the connection
public function getConnection() {
return $this->conn;
}
// function to close the connection
public function closeConnection() {
if ($this->conn != null)
$this->conn->close();
}
// function to get user email
public function getUserDetails($email)
{
$returnValue = array();
$sql = "select * from ap_users where user_email='" . $email . "'";
$result = $this->conn->query($sql);
if ($result != null && (mysqli_num_rows($result) >= 1)) {
$row = $result->fetch_array(MYSQLI_ASSOC);
if (!empty($row)) {
$returnValue = $row;
}
}
return $returnValue;
}
// get user details using email and password
public function getUserDetailsWithPassword($email, $userPassword, $roleid)
{
$returnValue = array();
$sql = "select id,user_email from ap_users where user_email='" . $email . "' and user_password='" .$userPassword . "' and user_roleid='" . $roleid . "'";
$result = $this->conn->query($sql);
if ($result != null && (mysqli_num_rows($result) >= 1)) {
$row = $result->fetch_array(MYSQLI_ASSOC);
if (!empty($row)) {
$returnValue = $row;
}
}
return $returnValue;
}
// register user with all fields
public function registerUser($email, $password, $username, $fname, $lname, $mobile, $roleid)
{
$sql = "insert into ap_users set user_email=?, user_password=?, user_username=?, user_fname=?, user_lname=?, user_mobile=?, user_roleid=?";
$statement = $this->conn->prepare($sql);
if (!$statement)
throw new Exception($statement->error);
$statement->bind_param("sssssss", $email, $password, $username, $fname, $lname, $mobile, $roleid);
$returnValue = $statement->execute();
return $returnValue;
}
}
?>
and my UserLogin.php is as under:
<?php
require("Conn.php");
require("MySQLDao.php");
$email = htmlentities($_POST["email"]);
$password = htmlentities($_POST["password"]);
$returnValue = array();
if(empty($email) || empty($password))
{
$returnValue["status"] = "error";
$returnValue["message"] = "Missing required field";
echo json_encode($returnValue);
return;
}
$secure_password = md5($password);
$dao = new MySQLDao();
$dao->openConnection();
$userDetails = $dao->getUserDetailsWithPassword($email,$secure_password);
if(!empty($userDetails))
{
$returnValue["status"] = "Success";
$returnValue["message"] = "User is logged in";
$returnValue["role"] = "'" .$roleid. "'";
echo json_encode($returnValue);
} else {
$returnValue["status"] = "error";
$returnValue["message"] = "User is not found";
echo json_encode($returnValue);
}
$dao->closeConnection();
?>
problem here is when i push the $roleid value always it shows null.
result is like this: {"status":"Success","message":"User is logged in","role:"""}
added MySqlDao getUserDetailsWithPassword() method
$sql = "select id,user_email,user_roleid from ap_users where user_email='" . $email . "' and user_password='" .$userPassword . "' and user_roleid='" . $roleid . "'";
and in user login changed
$returnValue["role"] = "'" .$roleid. "'"; line to $returnValue['user_roleid'] = $userDetails['user_roleid'];
this accomplish my desired result!
I just started learning, but why is it that when I don't fill the info in the URL it connects to the database, but when I fill it in it gives a fatal error?
Ex. when I type
http://ehlien.com/php/signup.php?firstname=Mohamed&lastname=Mohamed&username=alpha&email=mohamed.mohd#hotmail.com&password=mohamed
It throws:
Fatal error: Uncaught exception 'Exception' with message 'Failed to connect to database' in /home/torokage/public_html/php/classes/DB.class.php:22 Stack trace: #0 /home/torokage/public_html/php/signup.php(35): DB->connect() #1 {main} thrown in /home/torokage/public_html/php/classes/DB.class.php on line 22
But when I type
http://ehlien.com/php/signup.php
It gives me my error I set up:
{"status":"400","message":"Please fill in the missing information..."}
I don't have a lot of knowledge on php and mysql, just trying to figure it out on my own and through some tutorials but I can't get this to work to continue...
CODE, signup.php:
<?php
require('classes/User.class.php');
require('classes/DB.class.php');
require('classes/Connection.class.php');
$firstname = null;
$lastname = null;
$username = null;
$email = null;
$password = null;
$repassword = null;
if (empty($_REQUEST["firstname"]) ||
empty($_REQUEST["lastname"]) ||
empty($_REQUEST["username"]) ||
empty($_REQUEST["email"]) ||
empty($_REQUEST["password"]))
{
$returnError["status"] = "400";
$returnError["message"] = "Please fill in the missing information...";
echo json_encode($returnError);
return;
}
$firstname = htmlentities($_REQUEST["firstname"]);
$lastname = htmlentities($_REQUEST["lastname"]);
$username = htmlentities($_REQUEST["username"]);
$email = htmlentities($_REQUEST["email"]);
$password = md5(htmlentities($_REQUEST["password"]));
$DB = new DB(Connection::$db_host, Connection::$db_name, Connection::$db_user, Connection::$db_pass);
$DB->connect();
$checkUsername = $DB->checkIfUsernameExists($username);
if (!empty($checkUsername))
{
$returnError["status"] = "400";
$returnError["message"] = "That username has already been taken. Please try again...";
echo json_encode($returnError);
return;
}
$checkEmail = $DB->checkIfEmailExists($email);
if (!empty($checkEmail))
{
$returnError["status"] = "400";
$returnError["message"] = "That email has already been taken. Please try again...";
echo json_encode($returnError);
return;
}
$signUpUser = $DB->signUpUser($firstname, $lastname, $username, $email, $password);
if ($signUpUser)
{
$userDetails = $DB->getUserDetails($username);
$user["status"] = "200";
$user["message"] = "Success! You have now been registered.";
$user["ID"] = $userDetails["ID"];
$user["firstname"] = $userDetails["firstname"];
$user["lastname"] = $userDetails["lastname"];
$user["username"] = $userDetails["username"];
$user["email"] = $userDetails["email"];
}
else
{
$user["status"] = "400";
$user["message"] = "Sorry, this account has already been taken. Please try again...";
}
$DB->disconnect();
echo json_encode($user);
?>
DB.class.php
<?php
class DB {
protected $db_host = null;
protected $db_name = null;
protected $db_user = null;
protected $db_pass = null;
protected $db_conn = null;
protected $db_resu = null;
// Constructor
function __construct($db_host, $db_name, $db_user, $db_pass) {
$this->db_host = $db_host;
$this->db_name = $db_name;
$this->db_user = $db_user;
$this->db_pass = $db_pass;
}
// Connect to database
public function connect() {
$this->db_conn = new MySQLi($this->db_host, $this->db_name, $this->db_user, $this->db_pass);
if (mysqli_connect_errno())
throw new Exception("Failed to connect to database");
$this->db_conn->set_charset("utf8");
}
// Disconnect from database
public function disconnect() {
if ($this->db_conn != null)
$this->db_conn->close();
}
// Check if username exists
public function checkIfUsernameExists($username) {
$result = mysql_query("SELECT USERNAME FROM USERS WHERE EMAIL = '$username'");
if(mysql_num_rows($result) == 0){
return false;
} else {
return true;
}
}
// Check if email exists
public function checkIfEmailExists($email) {
$result = mysql_query("SELECT EMAIL FROM USERS WHERE EMAIL = '$email'");
if(mysql_num_rows($result) == 0){
return false;
} else {
return true;
}
}
// Get user informationd
public function getUserDetails($username) {
$command = mysql_query("SELECT * FROM USERS WHERE USERNAME = '$username'");
$value = array();
$result = $this->db_conn->query($command);
if ($result != null && (mysqli_num_rows($result) >= 1)) {
$row = $result->fetch_array(MYSQLI_ASSOC);
if (!empty($row)) {
$value = $row;
}
}
return $value;
}
// Sign up new user
public function signUpUser($firstname, $lastname, $username, $email, $password) {
$command = "INSERT INTO USERS SET FIRSTNAME=?, LASTNAME=?, USERNAME=?, EMAIL=?, PASSWORD=?";
$sql = $this->db_conn->prepare($command);
if (!$sql)
throw new Exception($sql->error);
$sql->bind_param("sssss", $firstname, $lastname, $username, $email, $password);
$value = $sql->execute();
return $value;
}
}
?>
When you didn't use any value or parameters, it's showing the error set up by you because it couldn't pass the validation step set up by you.
But when you are passing the values or parameters, it passes your validation and tries to connect with the database first as per this code of yours:
$DB = new DB(Connection::$db_host, Connection::$db_name, Connection::$db_user, Connection::$db_pass);
$DB->connect();
But it throws an exception: Failed to connect to database meaning that your database connection credentials are wrong and thus, can not connect with the database.
You may get more friendly error message by changing inside the public function connect() of DBclass to this:
// Connect to database
public function connect() {
try {
$this->db_conn = new MySQLi($this->db_host, $this->db_name, $this->db_user, $this->db_pass);
$this->db_conn->set_charset("utf8");
} catch (Exception $e ) {
echo "Failed to connect to database";
echo "Error: " . $e->message; // remove when in live...
}
}
I'm trying to retrieve data from my table using PDO, only I can't seem to output anything to my browser, I just get a plain white page.
try {
// Connect and create the PDO object
$conn = new PDO("mysql:host=$hostdb; dbname=$namedb", $userdb, $passdb);
$conn->exec("SET CHARACTER SET utf8"); // Sets encoding UTF-8
$lastIndex = 2;
$sql = "SELECT * FROM directory WHERE id > :lastIndex AND user_active != '' LIMIT 20"
$sth = $conn->prepare($sql);
$sth->execute(array(':lastIndex' => $lastIndex));
$c = 1;
while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
echo 'ALL STYLING ETC RESULTS HERE';
$c++;
}
$conn = null; // Disconnect
}
EXAMPLE.
This is your dbc class
<?php
class dbc {
public $dbserver = 'server';
public $dbusername = 'user';
public $dbpassword = 'pass';
public $dbname = 'db';
function openDb() {
try {
$db = new PDO('mysql:host=' . $this->dbserver . ';dbname=' . $this->dbname . ';charset=utf8', '' . $this->dbusername . '', '' . $this->dbpassword . '');
} catch (PDOException $e) {
die("error, please try again");
}
return $db;
}
function getAllData($qty) {
//prepared query to prevent SQL injections
$query = "select * from TABLE where qty = ?";
$stmt = $this->openDb()->prepare($query);
$stmt->bindValue(1, $qty, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $rows;
}
?>
your PHP page:
<?php
require "dbc.php";
$getList = $db->getAllData(25);
foreach ($getList as $key=> $row) {
echo $row['columnName'] .' key: '. $key;
}