0

I'm very new to PHP/MySQL so please understand, however am trying to implement a complex login system into my site. So far I have the registration done, however have not done it using prepared statements, and have just used MySQLi instead. Since it's necessary to prevent SQL injection, I need to somehow change this code to prepared statements; I've tried counteless times and just get a failure with the statement execution.

This is the initial, working (but un-prepared) code. Since this may be a big ask, I'm happy to pay anyone a small fee to help.

//Declaring variables as whitespace so nothing will be displayed below the form until submission.
$fe_firstName = " ";
$fe_lastName = " ";
$fe_email = " ";
$fe_emailconf = " ";
$fe_username = " ";
$fe_pw = " ";
$fe_pwconf = " ";
$fe_terms = " ";
$fe_usernameInvalid = " ";
$fe_emailInvalid = " ";
//Declaring verification variables to ensure duplicate users aren't created.
$verifyUsername = $_POST['username'];
$verifyEmail = $_POST['email'];

//Setting up array, if zero errors occur the array will stay empty.
$errors = array();


//The URL of the signup page.
//The full URL of the page the form was submitted from.
$current = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$referrer = $_SERVER['HTTP_REFERER'];

//Ensure form comes from VAL website.
if ( $referrer == $current ) {

if($_SERVER['REQUEST_METHOD'] == 'POST'){
 /**
  * Validate forms
    * Match regex
    * Ensure pass & email confirmations match
    */
    if(0 === preg_match("/^[a-z\-]{2,20}$/i", $_POST['firstName'])){
        $errors['e_firstName'] = "Your first name cannot be empty.";
        $fe_firstName = "Your first name cannot be empty.";
    }
    if(0 === preg_match("/^[a-z\-]{2,20}$/i", $_POST['lastName'])){
        $errors['e_lastName'] = "Your last name cannot be empty.";
        $fe_lastName = "Your last name cannot be empty.";
    }
    if(0 === preg_match("/^[a-zA-Z0-9]+[a-zA-Z0-9_.-]+[a-zA-Z0-9_-]+@[a-zA-Z0-9]+[a-zA-Z0-9.-]+[a-zA-Z0-9]+.[a-z]{2,4}$/", $_POST['email'])){
        $errors['e_email'] = "Please enter a valid E-Mail address.";
        $fe_email = "Please enter a valid E-Mail address.";
    }
    if(0 !== strcmp($_POST['email'], $_POST['emailconf'])){
        $errors['e_emailconf'] = "Please ensure your E-Mail addresses match.";
        $fe_emailconf = "Please ensure your E-Mail addresses match.";
    }
    if(0 === preg_match("/^[a-z\d_]{3,20}$/i", $_POST['username'])){
        $errors['e_username'] = "Please enter a valid username.";
        $fe_username = "Please enter a valid username.";
    }
    if(0 === preg_match("/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,56}$/", $_POST['pw'])){
        $errors['e_pw'] = "Please follow the password instructions. You must have at least one number, one lower-case, and one upper-case letter.";
        $fe_pw = "Please follow the password instructions. You must have at least one number, one lower-case, and one upper-case letter.";
    }
    if(0 !== strcmp($_POST['pw'], $_POST['pwconf'])){
        $errors['e_pwconf'] = "Please ensure your passwords match.";
        $fe_pwconf = "Please ensure your passwords match.";
    }
    if(!isset($_POST['terms'])){
        $errors['e_terms'] = "You must accept the Terms and Conditions.";
        $fe_terms = "You must accept the Terms and Conditions.";
    }
 /**
    * Check if username and email address already exist.
    * If so, add error to validity array.
    */
    $usernameCheck = mysqli_query($con, "SELECT * FROM users WHERE username='".$verifyUsername."'");
    if($usernameCheck->num_rows){
        $errors['e_usernameInvalid'] = "Username already exists.";
        $fe_usernameInvalid = "Username already exists.";
    }
    $emailCheck = mysqli_query($con, "SELECT * FROM users WHERE email='".$verifyEmail."'");
    if($emailCheck->num_rows){
        $errors['e_emailInvalid'] = "Email already exists.";
        $fe_emailInvalid = "Email already exists.";
    }

    //If no validation errors
    if(0 === count($errors)){
    /***
        * Sanitize code
        * Clean dangerous chars for DB
        */
        $send_firstName = mysqli_real_escape_string($con, $_POST['firstName']);
        $send_lastName = mysqli_real_escape_string($con, $_POST['lastName']);
        $send_email = mysqli_real_escape_string($con, $_POST['email']);
        $send_username = mysqli_real_escape_string($con, $_POST['username']);
        $password = mysqli_real_escape_string($con, $_POST['pw']);
        //HASH & ready password
        //
        // Instantiate new instance of class
        $hash_password = new Hash_Password();
        // Hash the password
        $hash = $hash_password->hash($password);
        $send_pw = $hash;
        //Autoset non-user-input values to 0
    $send_wins = 0;
    $send_losses = 0;
    $send_played = 0;
    $send_earnings = 0;
        //Obtain time of form submission = Time registered.
        $datum = new DateTime();
        $send_regDate = $datum->format('Y-m-d H:i:s');
        $send_lastLogin = $send_regDate;
        $send_rolePermissions = 0;

        //Insert query time.
    $sql = "
    INSERT INTO users (first_name, last_name, username, password, email, last_login, date_joined, wins, losses, played, earnings, permissions) VALUES
    ('{$send_firstName}','{$send_lastName}','{$send_username}','{$send_pw}','{$send_email}','{$send_lastLogin}','{$send_regDate}','{$send_wins}','{$send_losses}','{$send_played}','{$send_earnings}','{$send_rolePermissions}')
    ";

        //Redirecting based on the connection result.
    if(!mysqli_query($con, $sql)){
            if (!headers_sent()) {
                exit(header("Location: registration_fail.php"));
            } else{
                ?>
            <script> location.replace("registration_fail.php"); </script>
                <?php
            }
    } else{
            if (!headers_sent()) {
                exit(header("Location: registration_success.php"));
            } else{
                ?>
            <script> location.replace("registration_success.php"); </script>
                <?php
            }
            mysqli_close($con);
    }

    }

}
}

A lot of the code is validation, and the "fe_" variables are echoed underneath the form. I believe all that needs changing is the $sql variable, the real_escape_strings, and the $usernameCheck and $emailCheck.

Again, my greatest apologies for the untidy question, but I couldn't find the answer elsewhere. P.S - The database is connected via PDO and has no problems.

Lewis
  • 29
  • 5

1 Answers1

0

You implemented server side validation that's really very good practice for beginner.

PHP prepared statement is very very simple and php.net is resource for this.

I just implemented PHP PDO. You can check and review the code from GitHub.

Ravi Roshan
  • 570
  • 3
  • 14