The registration should fail, if the username does not contain only letters - php

I want to check the username to contain only letters. If it doesn't contain any letters, the registration I want to fail. Is it good to use preg_match? Now if I input for username: a1, also filling the password, confirm password and type fields the registration is successful.
form.php
if (isset($_POST['submit'])){
/* if the username is alphabetic */
if (ctype_alpha(str_replace(' ', '', $username)) === false &&!empty($username) ) {
$errors[] = 'Userame must contain letters and spaces only';
}
/* if passwords match */
if((!empty($password) && !empty($repassword)) && ($password != $repassword)){
echo "Passwords do not match.";
}
if (!empty($_POST['username']) && !empty($_POST['password']) && !empty($_POST['type'])){
$sql = "INSERT INTO users (username, password, type) VALUES ('$username', '$password', '$type')";
$result = mysql_query($sql);
echo 'Successful Registration.';
}
else{
echo 'Please fill all the fields.';
}
}

If you're looking for just letters in the username, preg_match will work for you.
For example,
if(!preg_match("/^[a-zA-Z]+$/", $username)){
// if the username has non-letter characters
}
However, like the comments are saying, there are much better ways to approach preventing SQL injection attacks. Switching to prepared statements is a great start.

Related

Adding data to MySQL DB with PDO not working

I am trying to re-learn my web development skills for a current application project I am working on. I have verified my PHP back-end is getting the data passed to it from the HTML/JS form on the front-end. But when I submit the form the webpage does not mention any errors. Everything looks fine until I look at the database and see nothing was added. I do not see the echo at the end either that data was successfully added, or that it failed to add data.
register.php
<?php
include "conn.php";
if(empty($_POST['firstName']) || empty($_POST['lastName']) || empty($_POST['email']) || empty($_POST['password']) || empty($_POST['pin'])) {
echo "<br>Error: Please fill out all required fields.";
} else if($_POST['password'] != $_POST['confirmPassword']) {
echo "<br>Error: Passwords do not match.";
} else if($_POST['pin'] != $_POST['confirmPin']) {
echo "<br>Error: Pin codes do not match.";
} else if(strlen($_POST['password']) > 20 || strlen($_POST['password']) < 8) {
echo "<br>Error: Passwords must be between 8 and 20 characters in length.";
} else if(strlen($_POST['pin']) != 4) {
echo "<br>Error: Pin codes must be a maximum of 4 characters.";
} else if(strlen($_POST['firstName']) > 50 && strlen($_POST['lastName']) > 50 && strlen($_POST['email']) > 50) {
echo "<br>Error: First Name, Last Name, and E-mail fields must be shorter than 50 characters in length.";
} else if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
echo "<br>Error: You must use a valid e-mail address.";
} else {
echo "<br><br>Successfully checked all data!";
$options = [
'cost' => 12,
];
$hash = password_hash($_POST['password'], PASSWORD_BCRYPT, $options);
$numericPin = (int)$_POST['pin'];
$currentDateTime = date("Y-m-d H:i:s");
$stmt = $conn->prepare("INSERT INTO account (firstName, lastName, email, password, pin, registerDate) VALUES (:firstName, :lastName, :email, :password, :pin, :registerDate)");
$stmt->bindParam(":firstName", $_POST['firstName']);
$stmt->bindParam(":lastName", $_POST['lastName']);
$stmt->bindParam(":email", $_POST['email']);
$stmt->bindParam(":password", $hash);
$stmt->bindParam(":pin", $numericPin);
$stmt->bindParam(":registerdate", $currentDateTime);
if($stmt->execute()) {
echo "<br><br>Data added successfully";
} else {
echo "<br><br>Failed to add data";
}
}
?>
MySQL DB Structure:
MySQL DB Structure Picture Link
You have a misspelled placeholder
":registerdate"
You have this in the SQL
$stmt = $conn->prepare("INSERT INTO account (firstName, lastName, email, password, pin, registerDate) VALUES (:firstName, :lastName, :email, :password, :pin, :registerDate)");
Specifically :registerDate vs :registerdate, casing matters here.
A few other things:
change include to require ask youself will the script work without it, well no. Then it needs to be require. Include won't give you an error when it fails to find the file.
Change your validation to help your end users
$errors = [];
if(empty($_POST['firstName']) || empty($_POST['lastName']) || empty($_POST['email']) || empty($_POST['password']) || empty($_POST['pin']))
$errors[] ="<br>Error: Please fill out all required fields.";
if($_POST['password'] != $_POST['confirmPassword'])
$errors[] ="<br>Error: Passwords do not match.";
if($_POST['pin'] != $_POST['confirmPin']) ....
Then count the array
if(count($errors) > 0 ){
echo implode("\n", $errors);
}else{
//--- do insert
}
This way you can show them all the errors at once. Otherwise they have to submit, correct, submit, correct etc etc... This will get very frustrating very quickly and the last thing you want to do is frustrate your users, they may just leave. I have and will leave sites that don't show me the errors right away, I would rather find a site offering what I want that is properly build then deal with one that can't even do proper validation. It makes me wonder what else cant be trusted on the site. (but that is me and I have experience in this thing).
Naming Conventions (opinion):
I always name DB fields all lowercase with spaces replaced with _. This reduces a lot of these kinds of issues because, is it registerdate, registerDate or RegisterDate.
There are a few other things related to table names that I do, but I won't bore you with all that.
Cheers!
So just to add the answer here, it was simple. I added a try/catch block around where the statement was being executed (and where the script was dying). Found that there was some kind of duplicate placeholder usage or mismatch. Then I double checked my placeholders and found :registerDate was bound as :registerdate. Fixed and boom, adding to database. Thanks all for helping!

check if username doesnt contain numbers or other weird signs? PHP

i have a username but i want to check if the username doenst contain any numbers or other things that does not belong in a username.
Example:
if ($username !contain "1234567890/.,;'\[]") {
send username to db
} else {
echo 'your username is incorrect';
}
How do i do this?
the username is represents the real name in my code.
Among the 1000 ways you can do this, one is regular expressions:
if (!preg_match("![0-9/.,;'\\\[\]]!", $username)) {
//send username to db
} else {
echo 'your username is incorrect';
}
An alternative is to whitelist permitted characters rather than blacklist invalid ones:
//Allows letters and a single quote (not uncommon in some names)
if (preg_match("!^[A-Za-z']+$!", $username)) {
//send username to db
} else {
echo 'your username is incorrect';
}
Try preg_match
Searches username for a match to the regular expression given in pattern.

Values are not being added to the database

I am very new to PHP and Mysql. I have made a registeration form but the values being inputted are not being saved in my database. I don't know why. I am connected to the database. Could anyone give me some insight? By the way, I know you are going to say "Mysql" is deprecated. But I am just starting out and learning how all of this works. As soon as I have a thorough understanding of the processes I am going to change my code to Mysqli...
<?php
//form data
$submit = strip_tags($_POST['submit']);
$fname = strip_tags($_POST['fname']);
$lname = strip_tags($_POST['lname']);
$usernamereg = strip_tags($_POST['usernamereg']);
$passwordreg = strip_tags($_POST['passwordreg']);
$email = strip_tags($_POST['email']);
$emailcheck = strip_tags($_POST['emailcheck']);
$date = date("Y-m-d");
if($submit)
{
//check for existence
if($fname&&$lname&&$usernamereg&&$passwordreg&&$email&&$emailcheck)
{
//encrypt password
$password = md5($passwordreg);
if(strlen($usernamereg)>25)
{
echo "Username must be 25 characters or less.";
}
else
{
//checks password length
if(strlen($passwordreg)<6)
{
echo "Passwords must be atleast 6 characters long";
}
else
{
if($email!=$emailcheck)
{
echo "emails to not match";
}
else
{
//open database
$connect = mysql_connect("localhost","root","clandestine");
mysql_select_db("user_db"); //selects database
$queryreg = mysql_query("INSERT INTO users VALUES('','$date','$fname','$lname','$usernamereg','$passwordreg','$email','$emailcheck'");
echo "You have been registered!";
}
}
}
}
else
echo "Please fill in <b>all</b> fields!";
Try assigning the columns in the INSERT query.
$queryreg = mysql_query("INSERT INTO users (`randomField`, `date`, `first_name`, `last_name`, `username`, `password`, `email`, `email_check`) VALUES ('','$date','$fname','$lname','$usernamereg','$passwordreg','$email','$emailcheck'");
What is the first column supposed to be?
Have you done any sanity checking? (ie, printing test data to the screen at certain points in the code to make sure your IF statements are evaluating to true?
Additionally, try saving your INSERT query as a variable string:
$query = "INSERT INTO.............";
and then printing it to the screen. Copy and paste that query into PHPMyAdmin (if you have access to it) and see if there are any errors with your statement. PMA will tell you what errors there are, if any.
EDIT: Also, please don't ever MD5 a password or other highly sensitive data. Use a secure algorithm and salt the password. If you're unsure of what this all means:
refer to this link
What do you get if you do:
$query = "INSERT INTO users
(date, first_name, last_name, username, password, email, email_check)
VALUES
('$date','$fname','$lname','$usernamereg','$passwordreg','$email','$emailcheck')";
mysql_query($query)or die('Error: <br />'.$query.'<br />'.mysql_error());
Note the removal of the backticks was just to simplify the code. It's correct to leave them in but with no spaces etc in your column names it should work anyway. Oh, and this is NOT good practice for production, of course. Just really clear debug.

PHP form validation using preg_match for password checks

This is a general question on password form validation and using a combination of uppercase, lowercase, numbers and characters used.
Research has showed that preg_match is required to validate the password (or whatever variable you use): (preg_match("/^.(?=.{8,})(?=.[0-9])(?=.[a-z])(?=.[A-Z]).*$/")
Though how would how would i integrate this into the if statement below? I've tried combining them using && though this seems to ignore the preg_match part. if(($pass == $pass2) && (preg_match("/^.(?=.{8,})(?=.[0-9])(?=.[a-z])(?=.[A-Z]).*$/"))
Any advice would be appreciated.
<?php
require "dbconn.php";
$username = ($_GET['username']);
$email = ($_GET['email']);
$pass = ($_GET['pwd1']);
$pass2 = ($_GET['pwd2']);
$USN = ($_GET['schoolnumber']);
$matching = 0;
if($pass == $pass2)
{
echo "<script type='text/javascript'> window.alert('Your details have been successfully registered, please proceed to login with your new credentials!')</script>";
echo '<script>javascript:window.close();</script>';
$query = "INSERT INTO customer VALUES ('".$username."','".$email."','".$pass."','face1.jpg','".$USN."','N')";
$results = mysql_query($query) or die (mysql_error());
$results1 = mysql_query($query1) or die (mysql_error());
}
else{
header('Location:register.php?matching=1');
}
?>
preg_match requires two arguments the pattern to look for and the string to test. Plus I'm not sure if the regular expression you are using would work anyway. Try something like.
$pattern = '/(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}/';
if (($pass1 == $pass2) && preg_match($pattern, $pass1)) {
...
}
You only need to match against one of the passwords because should ($pass1 == $pass2) fail then the preg_match isn't even preformed.
The regex above checks that the password is at least 8 characters long and contains at least one of each of lowercase, uppercase and a number

New PHP app - Salting and securing user passwords

I am setting up a new PHP app and would like to learn to salt and secure user password. I am unsure about which step during registration I need to do this at. Also, do I need to change my login forms as well?
if(isset($_POST['submit'])){
//protect and then add the posted data to variables
$username = protect($_POST['username']);
$password = protect($_POST['password']);
$passconf = protect($_POST['passconf']);
$email = protect($_POST['email']);
//check to see if any of the boxes were not filled in
if(!$username || !$password || !$passconf || !$email){
//if any weren't display the error message
echo "<center>You need to fill in all of the required filds!</center>";
}else{
//if all were filled in continue checking
//Check if the wanted username is more than 32 or less than 3 charcters long
if(strlen($username) > 32 || strlen($username) < 3){
//if it is display error message
echo "<center>Your <b>Username</b> must be between 3 and 32 characters long!</center>";
}else{
//if not continue checking
//select all the rows from out users table where the posted username matches the username stored
$res = mysql_query("SELECT * FROM `users` WHERE `username` = '".$username."'");
$num = mysql_num_rows($res);
//check if theres a match
if($num == 1){
//if yes the username is taken so display error message
echo "<center>The <b>Username</b> you have chosen is already taken!</center>";
}else{
//otherwise continue checking
//check if the password is less than 5 or more than 32 characters long
if(strlen($password) < 5 || strlen($password) > 32){
//if it is display error message
echo "<center>Your <b>Password</b> must be between 5 and 32 characters long!</center>";
}else{
//else continue checking
//check if the password and confirm password match
if($password != $passconf){
//if not display error message
echo "<center>The <b>Password</b> you supplied did not math the confirmation password!</center>";
}else{
//otherwise continue checking
//Set the format we want to check out email address against
$checkemail = "/^[a-z0-9]+([_\\.-][a-z0-9]+)*#([a-z0-9]+([\.-][a-z0-9]+)*)+\\.[a-z]{2,}$/i";
//check if the formats match
if(!preg_match($checkemail, $email)){
//if not display error message
echo "<center>The <b>E-mail</b> is not valid, must be name#server.tld!</center>";
}else{
//if they do, continue checking
//select all rows from our users table where the emails match
$res1 = mysql_query("SELECT * FROM `users` WHERE `email` = '".$email."'");
$num1 = mysql_num_rows($res1);
//if the number of matchs is 1
if($num1 == 1){
//the email address supplied is taken so display error message
echo "<center>The <b>E-mail</b> address you supplied is already taken</center>";
}else{
//finally, otherwise register there account
//time of register (unix)
$registerTime = date('U');
//make a code for our activation key
$code = md5($username).$registerTime;
//insert the row into the database
$res2 = mysql_query("INSERT INTO `users` (`username`, `password`, `email`, `rtime`) VALUES('".$username."','".$password."','".$email."','".$registerTime."')");
//send the email with an email containing the activation link to the supplied email address
You absolutely must read this article: Enough with the rainbow tables.
Summary: If you're not using BCrypt, you're doing it wrong. No ifs, no buts. (This also means that all the suggestions to use MD5 or SHA-1 or SHA-512 or anything else are wrong too.)
As for when you do it, it should be sometime before you insert it into the DB but after you check it for errors.
Some suggestions though.
Instead of nesting the ifs during error checking so that if username fails, password doesn't get checked, and if password fails, passconf doesn't get checked try something like this:
$errors = array();
if(strlen($username) > 32 || strlen($username) < 3)
{
$errors['username'] = "Username must be between 3 and 32 characters.";
}
else
{
$res = mysql_query("SELECT * FROM `users` WHERE `username` = '".$username."'");
$num = mysql_num_rows($res);
if($num == 1)
{
$errors['username'] = "Username already exists!";
}
}
if(strlen($password) < 5 || strlen($password) > 32)
{
$errors['password'] = "Password must be between 5 and 32 characters.";
}
else if($password != $confpass)
{
$errors['password'] = "Passwords do not match.";
}
etc. etc. etc. so that each field is checked and errors returned if there are any. Then you do something like this at the end:
if(!count($errors)) //or if(count($errors) == 0)
{
//code to process login/registration/whatever Do password hashing here.
}
else
{
//There were errors, do something else
}
This way you get all errors, so you can tell the user everything that's wrong with their input at once, and the code isn't as deeply nested.
Also, the people having the flame war on what hashing algorithm to use above, just ignore them unless you're trying to create a US Government or Corporate application. No attackers will care enough to actually attack otherwise, unless your application gets popular enough to warrant an attack. It is important that you hash it in some way though.
SECURITY IS HARD. Don't do it yourself but let the exports figure it out. You could read there specs/implementations(if open):
openid
google friend connect
facebook connect
twitter single sign in
just to name a few options.

Categories