I'm looking to create a sign-up page for a large-scale website which means I'm using a lot more layers of validation then I would normally do, given this should be common practice but in this particular case more than any other situation it is imperative.
I've already written most of the code required and formatted it in an order which I believed wouldn't lead to any undefined variable errors, however, upon form submission it doesn't create a new SQL row and doesn't return any errors under the error handling areas of the form validation. In all fairness, the error handling is quite simple at this point and is not a final version, just what I put in place to help me debug and troubleshoot any issues which should arise.
Here's the PHP code, and the snippet of the piss-poor error handling that is supposed to output an error message if an error occurs, to re-state, this error handling isn't final.
$conn = mysqli_connect('localhost', 'root2', '123', 'db');
$signupConditionsMet = "0";
if (isset($_POST["email"]) && isset($_POST["username"]) && isset($_POST["password"]) && isset($_POST["passwordCheck"]) && isset($_POST["birthdate"])) {
$signupConditionsMet = "1";
$birthGood = true;
$passGood = false;
$nameGood = false;
$emailGood = false;
}
$usernameSearch = $conn->prepare("SELECT * FROM users WHERE username = ?");
$userInsertion = $conn->prepare("INSERT INTO users (username, passwd, birthdate, email) VALUES (?,?,?,?)");
$nameErr = $emailErr = $passErr = $birthErr = "";
$name = $email = $pass = $birth = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = $_POST["username"];
$email = $_POST["email"];
$pass = $_POST["password"];
$birthdate = $_POST["birthdate"];
$passCheck = $_POST["passwordCheck"];
}
if ($signupConditionsMet === "1"){
function test_input($name) {
if (!preg_match("/^[a-z\d_]{2,15}$/i",$name)) {
$nameErr = "Only letters and white space allowed";
} else {
$nameGood = true;
return $name;
echo "did name ez";
}
}
function test_input2($email){
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$emailErr = "Invalid email format";
} else {
$emailGood = true;
return $email;
echo "did email ez";
}
}
function test_input3($password){
if (!preg_match("/^[a-z\d_]{2,15}$/",$pass)) {
$passErr = "Invalid password format";
} else if (!preg_match("/^[a-z\d_]{2,15}$/",$passCheck)){
$passErr = "Invalid password check format";
} else if ($_POST["password"] !== $_POST["passwordCheck"]){
$passErr = "Passwords do not match";
} else {
$passwd2 = AES_ENCRYPT($_POST["password"], 'mysecretstring');
$passwdGood = true;
return $passwd2;
echo "did pass ez";
}
}
}
if (($signupConditionsMet === "1") && ($birthGood === true) && ($nameGood === true) && ($passwdGood === true) && ($emailGood === true)) {
if ($usernameSearch->execute(array($_POST['username']))) {
while ($row = $usernameSearch->fetch()) {
if (!empty($row['id'])) {
$creationError = "This username is already taken";
} else {
$userInsertion->bindParam(1, $name);
$userInsertion->bindParam(2, $passwd2);
$userInsertion->bindParam(3, $birthdate);
$userInsertion->bindParam(4, $email);
$userInsertion->execute();
header('Location: userlanding.php');
}
}
}
}
/* PHP inside the HTML to output errors */
<?php if ($signupConditionsMet === "1") { echo "all inputs received"; echo $_SERVER["REQUEST_METHOD"];} else { echo "drats, they weren't all there"; echo $name; echo $email; echo $birthdate; echo $pass; echo $passCheck;}?>
<?php if ($passErr) { echo $passErr;} else if ($nameErr) { echo $nameErr;} else if ($emailErr) { echo $emailErr;} else if ($birthErr) { echo $birthErr;} ?>
Disregarding the previously admitted terrible error handling, I can't seem to wrap my head around why it doesn't work in its current form. It returns (from the client-side reporting) that all inputs were received and there isn't any fatal errors thrown from running the PHP code. In addition, the second client-side code which prints any errors doesn't print anything either, implying that all functions operated correctly, however, the echos at the bottom of the input tests don't echo the strings they've been assigned, implying those didn't work, but there was no errors. Hmm. Perhaps I'm missing something blatantly obvious regarding my syntax but I don't see why it wouldn't work. Any help would be appreciated.
Related
i have two variables mobile and email now i want to validate both but i want the user to leave blank one of the fields if user does not have one for ex if a user does not want to register with his email then he can go to mobile number for registration and vice versa this is my validation code
<?php
$emailError = "";
$fullnameError = "";
$usernameError = "";
$passwordError = "";
$mobileerror = "";
$errors = 0;
if ((isset($_POST['submit']))) {
$email = strip_tags($_POST['email']);
$fullname = strip_tags($_POST['fullname']);
$username = strip_tags($_POST['username']);
$password = strip_tags($_POST['password']);
$mobile = strip_tags($_POST['mobile']);
$fullname_valid = $email_valid = $mobile_valid = $username_valid = $password_valid = false;
if (!empty($fullname)) {
if (strlen($fullname) > 2 && strlen($fullname) <= 30) {
if (!preg_match('/[^a-zA-Z\s]/', $fullname)) {
$fullname_valid = true;
# code...
} else {
$fullnameError = "fullname can contain only alphabets <br>";
$errors++;
}
} else {
$fullnameError = "fullname must be 2 to 30 char long <br>";
$errors++;
}
} else {
$fullnameError = "fullname can not be blank <br>";
$errors++;
}
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$query2 = "SELECT email FROM users WHERE email = '$email'";
$fire2 = mysqli_query($con, $query2) or die("can not fire query" . mysqli_error($con));
if (mysqli_num_rows($fire2) > 0) {
$emailError = $email . "is already taken please try another one<br> ";
} else {
$email_valid = true;
}
# code...
} else {
$emailError = $email . "is an invalid email address <br> ";
$errors++;
}
# code...
if ($mobile) {
$query4 = "SELECT mobile FROM users WHERE mobile = '$mobile'";
$fire4 = mysqli_query($con, $query4) or die("can not fire query" . mysqli_error($con));
if (mysqli_num_rows($fire4) > 0) {
$mobileerror = "is already taken please try another one<br> ";
} else {
$mobile_valid = true;
}
}
if (!empty($username)) {
if (strlen($username) > 4 && strlen($username) <= 15) {
if (!preg_match('/[^a-zA-Z\d_.]/', $username)) {
$query = "SELECT username FROM users WHERE username = '$username'";
$fire = mysqli_query($con, $query) or die("can not fire query" . mysqli_error($con));
if (mysqli_num_rows($fire) > 0) {
$usernameError = '<p style="color:#cc0000;">username already taken</p>';
$errors++;
} else {
$username_valid = true;
}
} else {
$usernameError = "username can contain only alphabets <br>";
$errors++;
}
} else {
$usernameError = "username must be 4 to 15 char long <br>";
$errors++;
}
} else {
$usernameError = "username can not be blank <br>";
$errors++;
}
if (!empty($password)) {
if (strlen($password) >= 5 && strlen($password) <= 15) {
$password_valid = true;
$password = md5($password);
# code...
} else {
$passwordError = $password . "password must be between 5 to 15 character long<br>";
$errors++;
}
# code...
} else {
$passwordError = "password can not be blank <br>";
$errors++;
}
//if there's no errors insert into database
if ($errors <= 0) {
if ($fullname_valid && ($email_valid || $mobile_valid )&& $password_valid && $username_valid) {
$query = "INSERT INTO users(fullname,email,username,password,avatar_path) VALUES('$fullname','$email','$username','$password','avatar.jpg')";
$fire = mysqli_query($con, $query) or die("can not insert data into database" . mysqli_error($con));
if ($fire) {
header("Location: dashboard.php");
}
}
}
}
?>
now when i use email and leave blank mobile the code works fine but when i use email and leave blank mobile then error occurs how to solve this problem
Use one more flag
$isValid_email_mobile = FALSE;
When control flow enters into if (filter_var($email, FILTER_VALIDATE_EMAIL)) then on SUCCESS just set $isValid_email_mobile = TRUE; It will be same if control enters in condition if ($mobile) again on SUCCESS , set it as $isValid_email_mobile = TRUE;
When $isValid_email_mobile = FALSE; becomes TRUE then you know that of the field/variable has passed your requirement and its ready for DB INSERT
Then
In your last IF condition when you try to INSERT just change IF condition to the following
IF ($fullname_valid && $isValid_email_mobile && $password_valid && $username_valid)
One more thing whenever you are using Flag logic always set your flag to some default value before using it.
now when i use email and leave blank mobile the code works fine but when i use email and leave blank mobile then error occurs
you have:
if (!empty($fullname)) {}
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {}
if ($mobile) {}
if (!empty($username)) {}
if (!empty($password)) {}
To remove the error, try adding
if (!empty($mobile)) {
Also, I would suggest to wrap the statements a bit more. You only need one to fail in order to stop input. You could do something like this:
$mobileOrEmail = false;
if (!empty($fullname) && !empty($username) && !empty($password) {
//check fullname, username and password
if (!empty($mobile) {
//check mobile, if it passes
$mobileOrEmail = true;
}
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
//check email, if it passes
$mobileOrEmail = true;
}
if (!$mobileOrEmail) $errors++;
} else {
//missing input values
$errors++;
}
Personally, I would create a function for each input field.
function checkUsername($username){
//check username
return true;
}
function checkEmail($email) {
//check email
return true;
}
....
then you can run
if (checkUsername($username) && checkPassword($password)
&& checkFullname($fullname) && (checkEmail($email) || checkEmail($email)) {
//user input correct
} else {
//user input failed
}
Just to give it more structure
PFB code. DB connection is success but when try to register with register.php script in my android phone getting error page or getting please fill all values. I am not getting success. Kindly help. I am also using the URL register url in my java code as well http://xxxx/Userregistration/register.php.
register.php
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$name = $_POST['name'];
$username = $_POST['username'];
$password = $_POST['password'];
$email = $_POST['email'];
if ($name == '' || $username == '' || $password == '' || $email == '') {
echo 'please fill all values';
} else {
require_once('dbConnect.php');
$sql = "SELECT * FROM KumbhaApp WHERE username='$username' OR email='$email'";
$check = mysqli_fetch_array(mysqli_query($con, $sql));
if (isset($check)) {
echo 'username or email already exist';
} else {
require_once('dbConnect.php');
$sql = "INSERT INTO KumbhaApp (name,username,password,email) VALUES('$name','$username','$password','$email')";
}
}
if (!preg_match("/^[a-zA-Z ]*$/", $name)) {
$nameErr = "Only letters and white space allowed";
} else {
if (!preg_match("/([\w\-]+\#[\w\-]+\.[\w\-]+)/", $email)) {
$emailErr = "Invalid email format";
}
}
if (mysqli_query($con, $sql)) {
echo 'successfully registered';
header('Location: securedpage.php');
} else {
echo 'oops! Please try again!';
}
mysqli_close($con);
}
?>
It is not required, it is require. Your code
required ("http://localhost:8080/UserRegistration/dbConnect.php");
^
is wrong.
i'm worried about the security of my form. The idea is to make a form to participate in a contest in facebok. Basically just firstname, lastname, email. I've been searching through topics and there is a lot of info about security but i can't figure out what is enough security?
I know that there will always be a risk that someone finds a way to abuse the security, but i'd like to find a solution, which blocks the most of them. Also if there are obvious mistakes, please let me know.
Here is my code and all help and guidance is appreciated.
<?php
$dsn = 'mysql:dbname=dbname;host=localhost';
$user = '';
$password = '';
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
$firstErr = $lastErr = $emailErr = "";
$first = $last = $email = "";
function test_input($data)
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["first"])) {
$firstErr = "Name is required";
echo "<p>Firstname: $firstErr</p>";
} else {
$first = test_input($_POST["first"]);
// check if name only contains letters and whitespace
if (!preg_match("/^[a-zA-Z ]*$/",$first)) {
$firstErr = "Only letters and white space allowed";
echo "<p>Firstname: $firstErr</p>";
}
}
if (empty($_POST["last"])) {
$lastErr = "Name is required";
echo "<p>Lastname: $lastErr</p>";
} else {
$last = test_input($_POST["last"]);
// check if name only contains letters and whitespace
if (!preg_match("/^[a-zA-Z ]*$/",$last)) {
$lastErr = "Only letters and white space allowed";
echo "<p>Lastname: $lastErr</p>";
}
}
if (empty($_POST["email"])) {
$emailErr = "Email is required";
echo "<p>Email: $emailErr</p>";
} else {
$email = test_input($_POST["email"]);
// check if e-mail address is well-formed
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$emailErr = "Invalid email format";
echo "<p>Email: $emailErr</p>";
}
}
if ($firstErr == false && $lastErr == false && $emailErr == false) {
$query = "INSERT INTO contactstable (first,last,email) VALUES(:first,:last,:email)";
$statement = $dbh->prepare($query);
$statement->execute(array(
':first'=> $first,
':last'=> $last,
':email'=> $email
));
echo "<p>Thank you for participating!</p>";
}
else {
echo "Fix the missing or incorrect lines.";
}
}
?>
You are using PDO, it already implements the security measures for 1st order injection and when the queries are parametrized the 2nd order also prevented(2nd order injection means data has been cycled through the database once before being included in a query).
But there is no harm if you implements validations for the inputs.
$error1='';
$error2='';
$error3='';
$error4='';
$error5='';
$error6='';
$yourname='';
$email='';
$email2='';
$password='';
$password2='';
$country='';
if (isset($_POST['Registerme']))
{
$_POST['yourname']=$yourname;
$_POST['email']=$email;
$_POST['email2']=$email2;
$_POST['password']=$password;
$_POST['password2']=$password2;
$_POST['country']=$country;
if($yourname==''){
$error1='name required';
}
if($email==''){
$error2='email required';
}
if($email2==''){
$error3='required field';
}
if($password==''){
$error4='password required';
}
if($password2==''){
$error5='required field';
}
if($country==''){
$error6='country required';
}
if(empty($error1) && empty($error2) && empty($error3) && empty($error4) && empty($error5) && empty($error6))
{echo 'mysql query goes here and add the user to database';}
}///main one
else {$error1='';
$error2='';
$error3='';
$error4='';
$error5='';
$error6='';}
this is a registration validation script. in my registration form there are two email and password filelds.second fields are for confirmation.i want to check weather user typed same information in that both field.if i want to do that in this script should i use another if statement? or i should use else if? i am confused about that step...
Some comments:
You MUST sanitize input! Take a look at best method for sanitizing user input with php.
Your assignments: Instead of "$_POST['yourname']=$yourname;" it should be "$yourname=$_POST['yourname'];".
You're using a lot of variables for error control, and after that if all went well you simply forget the error messages in the last else block. Use some kind of array for error strings, and use it!
Are you sure you aren't validating usernames/passwords to not contain spaces or weird characters, or emails to be valid?
Some sample code...:
// Simple sanitize function, complete it
function sanitize_input ($inputstr) {
return trim(mysql_real_escape_string($inputstr));
}
if (isset ($_POST['Registerme']) {
// array of error messages to report
$error_messages = array();
$isvalid = true;
// Assignment
$yourname = sanitize_input ($_POST['yourname']);
$email = sanitize_input ($_POST['email']);
$email2 = sanitize_input ($_POST['email2']);
$password = sanitize_input ($_POST['password']);
$password2 = sanitize_input ($_POST['password2']);
$country = sanitize_input ($_POST['country']);
// Validation
if (empty ($yourname)) {
$error_messages[] = "You must provide an username";
}
if (empty ($password)) {
$error_messages[] = "You must provide a password.";
}
elseif ($password !== $password2) {
$error_messages[] = "Passwords do not match.";
}
// Same for email, you caught the idea
// Finally, execute mysql code if all ok
if (empty($error_messages)) {
// Execute mysql code
isvalid = true;
}
}
// After form processing, use isvalid which is false if there are errors
// and the error_messages array to report errors
add additional conditions to your second if statement.
e.g.
if($email=='' || $email != $email2){
...
Just add simple checks. I wouldn't combine the check with the general password check - as I can imagine you would like to tell the user what went wrong exactly.
if ($password1 !== $password2) {
// Add an specific error saying the passwords do not match.
}
I would replace the user of loose errors to an array like:
$aErrors = array();
if ($password1 !== $password2) {
$aErrors[] = 'Another specific error!';
}
if (empty($password1) || empty($password2)) {
$aErrors[] = 'Another specific error';
}
if (empty($aErrors)) {
// Process the form!
}
There are lots of issues with your code.
1. You are assinging $_POST['key'] = $somevalue, while I think you mean $somevar = $_POST['key']
2. Use an array for all error messages as it'll make your life a bit easier ..
3. To compare password use something like
if ($password1 !== $password2) {
}
so .....
$errors = array();
so you'd check something like ..
if ($password1 !== $password2) {
$errors[] = 'Password dont match';
}
if(count($errors) > 0) { //if there are errors
foreach($errors as $err) {
echo $err.' <br />';
}
} else {
// whatever you want to do if no error
}
I'll also suggest to sanitise the $_POST values before you use them in your queries.
I hope it helps.
I think you mean to do this:
$yourname = $_POST['yourname'];
$email = $_POST['email'];
$email2 = $_POST['email2'];
$password = $_POST['password'];
$password2 = $_POST['password2'];
$country = $_POST['country'];
Second this make use of an errors array:
$errors = array();
Third use nested ifs(just a suggestion)
if (!empty($_POST['password1'])) {
if ($_POST['password1'] != $_POST['password2']) {
$errors[] = '<font color="red">The 2 passwords you have entered do not match.</font>';
} else {
$password = $_POST['password1'];
}
} else {
$errors[] = '<font color="red">Please provide a password.</font>';
}
I have a form in a file register.php, and it posts to registerPost.php. Inside registerPost.php, I check against a few validation rules, then if any of them are flagged, I return to the first page and print the errors. In theory, that should work. But the validation goes through with no problems, even when I leave everything blank.
Here's the code in question:
$_SESSION["a"] = "";
$_SESSION["b"] = "";
$_SESSION["c"] = "";
$_SESSION["d"] = "";
$_SESSION["e"] = "";
$_SESSION["f"] = "";
$_SESSION["g"] = "";
if(empty($userEmail))
{
$_SESSION["a"] = "You must enter your email.";
}
if(!validEmail($userEmail))
{
$_SESSION["a"] = "Improper Email Format";
}
if(empty($password))
{
$_SESSION["b"] = "You must enter a password.";
}
if(strlen($password) < 5 || strlen($password) > 0)
{
$_SESSION["b"] = "Password must be at least 5 characters.";
}
if($password != $confPassword)
{
$_SESSION["c"] = "Passwords do not match";
}
if(empty($firstName))
{
$_SESSION["d"] = "First Name Required";
}
if(empty($lastName))
{
$_SESSION["e"] = "Last Name Required";
}
if(mysql_num_rows(mysql_query("SELECT * FROM users WHERE email = '$email'")) > 0)
{
$_SESSION["f"] = "This email address already exists in our database.";
}
if(!empty($_SESSION["a"]) || !empty($_SESSION["b"]) || !empty($_SESSION["c"]) || !empty($_SESSION["d"]) || !empty($_SESSION["e"]) || !empty($_SESSION["f"]))
{
header('Location: register.php');
}
Perhaps there is a more straightforward way to do this?
I like this way of registering all errors:
$errors = array();
if (empty($foo1))
$errors[] = "foo1 can't be left blank!";
else if (!preg_match(' ... ', $foo1))
$errors[] = "foo1 was not filled out correctly!";
if (empty($foo2))
$errors[] = "foo2 can't be left blank!";
// ...
if (empty($errors)) {
// do what you need
} else {
// notify the user of the problems detected
}
Do you really need to change the page by header?
I tried your code and it works for me.
Guessing from $username,$email and so on, I think you're doing some sanitizing on the $_POST data. If so, you should dump the $username, etc. to see, if that procedure is putting something in these variables.
Anyway, I like this way of validation better:
$errors = array();
if(empty($username))
{
$errors['username'] = 'Username cannot be empty!';
}
...
$_SESSION['errors'] = $errors;
if(count($errors) > 0) //Redirect...