Simple password validation in PHP - php

I'm a beginner to PHP trying to learn the basics of validating form data. I want to check if the password has been set, and if it has then to further check if it is the right length and has the right characters etc.
//check if set
if (empty($_POST['password']) {
//further validate - check length, characters etc
if (myFunction(($_POST['password'])) {
//success
$password = $_POST['password'];
}
else {
$error = "Password must be at least 8 characters and contain at least one number";
}
}
else {
$error = "Password is required";
}
The problem I'm having is if the user enters "0" as a password, the empty() function treats this as empty, and they're given the "Password is required" error, rather than the "Password must have..." etc error.
Using the isset() function instead wouldn't work either because an empty field would return an empty string, which would be considered to be set.
At the moment I have a workaround where I have a further conditional to check if the password is set to "0", but there must be a more elegant way.
Apologies if this has been covered in another question, I couldn't find anything. Thanks

Use isset() (and possibly strlen(trim()), not empty(). Although the way this code is shown, it will process only an empty password, and give an error to anyone who puts in a password.
if(isset($_POST['password']) && strlen(trim($_POST['password']))){
//process
}else{
//error
}

If you are just learning the basics, then use the function below. However, do remember in a live environment you will want to be hashing passwords properly. Read this link for more info: http://php.net/manual/en/faq.passwords.php
function PasswordCheck($password_string)
{
$password_string = trim($password_string);
if($password_string == '')
{
die("Password not entered");
}
elseif(strlen($password_string) < 8)
{
die("Password must be more than 8 characters in length");
}
elseif(!(preg_match('#[0-9]#', $password_string)))
{
die("Password must contain at least one number");
}
else
{
//Success, now process password
}
}
$password = $_POST['password'];
PasswordCheck($password);

You can use is_null() function or:
if ($_POST['password']==NULL)

please don't forget to use htmlspecialchars once before you use $_POST to make sure no XSS scripting attacK.
Isset function is better than empty in your case.
Additonally if you want user to get at least 8 characters and contain one number, use regular expression it is much better.

0 is considered to be empty in php. (source: http://php.net/empty )
You could get around this by checking if it is empty or if there is nothing in the string, or if it is exactly null, like so:
if ((empty($_POST['password']) || ($_POST['password']=='') ||
($_POST['password']===null) ) {
...
}
This should cover all your bases, however it is easy to check that something is there than checking a negative (I find it cognitively easier), such as making sure the password is entered, instead of checking to see whether it is not entered

The 'PHP Type Comparison Table' is your friend.
http://php.net/manual/en/types.comparisons.php
To check if the password has been set.
// Check if it has been set and contains characters.
if (isset($_POST['password']) && strlen($_POST['password']) > 0)
{
// Passed, now check for the right length, characters, etc.
if (myFunction(($_POST['password']))
{
// Success.
$password = $_POST['password'];
} else {
// Error.
$error = "Password must be at least 8 characters and contain at least one number";
}
} else {
// Failed.
$error = "Password is required";
}
If you require help with your 'myFunction()' function to check length, characters, etc then you will need to post that code as well.
Hope this helps.

Related

Allow no whitespace in required form field

I have a register form which allows users to create usernames and passwords. It requires the username field not be empty, but I need to require that it allow no whitespace at all.
I looked into preg_match() but I can't seem to get that to cooperate with my current code.
if ($_SERVER["REQUEST_METHOD"] == "POST") {
/* Validate Username */
if (empty(trim($_POST["username"]))) {
$username_err = "Username Required";
}
No need to use Regex for something so simple. With strrpos() you can find the last occurence of a substring (space character) in a string (username).
If strrpos doesn't find a match, it will return false. So all you have to do is check if strrpos returns anything else but false:
if (empty(trim($_POST["username"]))) {
$username_err = "Username Required";
} else if (strrpos($_POST["username"], ' ') !== false){
$username_space_err = "Space found in username";
}
Before calling any function on $_POST() I recommend calling isset() on the element to avoid receiving a Notice.
Using isset() will allow for the valid but unlikely username of 0.
Calling trim() on a not-set element will cause a Notice.
I don't see any advantage in checking from the back of the string for spaces with strrpos() so I'll simply call strpos().
If this is a simple pass/fail task (not trying to isolate the cause of the failure), use this:
Code: (Demo)
$_POST['username']="0";
if(isset($_POST['username']) && strlen($_POST['username']) && strpos($_POST['username'],' ')===false){
echo 'pass';
}else{
echo 'fail';
}
Output:
pass
The beauty in this one-liner conditional, is that as soon as one of the conditions fails, the rest are ignored and the fail message will be displayed.
If you want to get a little crazy with micro-optimization, you can remove the strlen() call and just check for the existence of a first character (see if the first "offset" isset).
if(isset($_POST['username'][0]) && strpos($_POST['username'],' ')===false){
echo 'pass';
}else{
echo 'fail';
}
And if we are putting tin-foil hats on, then a check to see that $_POST['username'] is not an array should be included before strpos() is called (in any of the solutions on this page).
if(isset($_POST['username'][0]) && !is_array($_POST['username']) && strpos($_POST['username'],' ')===false){

Regular expression to check repeating character or digit, check lowercase,uppercase,capital

please help me..i'm stuck in here..
What i actually want is to check the password from repeating single character or digit.
Requirement for repeating
aaaa = false,
abbb = false
abag = false
a33f = false
abcd1234 = true
there is only once for a character should have in password. If more than once repeated, error returns. So hard to explain.
this is my draft code.
1)first i need to check whether the global configuration for repeating character is allowed or not, if yes my password can have repeating char or digit otherwise it would't. After this, i need to check whether the global configuration for lowercase,uppercase or capitals allowed or not.
if($globalCOnf['repeat_pass']=="yes")//allowed
{
//do nothing
}
else //not allowed
{
//stuck here :(
if(preg_match('/(.)\1{1,}/',$user_input_pass)) //only check "aaaa" not "aba"
{
echo "change password";
}
else
{
if($globalCOnf['having_lower_upper_capital']=="yes")//allowed
{
//do nothing
}
else
{
// can't continue
}
}
}
You can use array_count_values for this (An alternate regex free solution)
<?php
$password = 'abcdfa';
if(max(array_count_values(str_split($password)))>1)
{
echo "Choose another password as words you can't have repeatable characters";
}
OUTPUT:
Choose another password as words you can't have repeatable characters
You get that output because a is repeated two times.
Answer for the question.
if($globalCOnf['repeat_pass']=="yes")//allowed
{
//do nothing
}
else //not allowed
{
if(max(array_count_values(str_split($user_pass)))>1)
{
echo "change your password now!!!";
}
else
{
if($globalCOnf['having_lower_upper_capital']=="yes")//allowed
{
//do nothing
}
else
{
if(preg_match('/[A-Z]/', $user_pass))
{
echo "Can't use uppercase";
}
}
}
}
100% working.. :)
Try something like this -
(\d+).*\1
If you get any match there is a repeated character.
Just allow zero or more characters between two duplicate characters. If there is a match, then the string failed to pass the validation.
Code: (Demo)
$passwords=['aaaa','abbb','abAg','a33f','abcd1234'];
foreach($passwords as $pass){
echo "$pass: ";
if(!preg_match('/([a-zA-Z\d]).*\1/',$pass)){
echo "valid\n";
}else{
echo "failed\n";
}
}
Output:
aaaa: failed
abbb: failed
abAg: valid
a33f: failed
abcd1234: valid
Or as one-line: echo preg_match('/([a-zA-Z\d]).*\1/',$pass)?'failed':'valid'
Using this type of pattern is much more direct that generating a temporary array of characters and counting their occurrences and checking the highest count.

PHP - Wondering about efficiency of nested IF statements for user registration

I am working on a little project of designing a website for my friends and myself.
I am currently building the user registration system and am wondering if the way I am checking user's entries is the best it could be.
Um, ignore the api stuff, it is for eve and likely irrelevant.
I have plans for the elses.
Essentially, I would like to know if this is acceptable in terms of... everything.
And if not, what could I do to improve this.
I am newer to PHP, please be kind :)
So, this is what I am currently using:
if (!empty($_POST['username'])
&& !empty($_POST['password1'])
&& !empty($_POST['password2'])
&& !empty($_POST['email1'])
&& !empty($_POST['email2'])
&& !empty($_POST['keyID'])
&& !empty($_POST['vCode'])
){
$api = new EVEAPI();
if ($api->getCharacterID($_POST['username']) != 0){
//The username is valid.
if ($_POST['password1'] == $_POST['password2']){
//Passwords match.
if ($_POST['email1'] == $_POST['email2']
&& filter_var($_POST['email1'], FILTER_VALIDATE_EMAIL)
){
//Emails match and are in valid format.
if ($api->isValidAPI($_POST['keyID'], $_POST['vCode'])){
//If the API returns something that is not an error, continue.
$xml = $api->getAPIKeyInfo($_POST['keyID'], $_POST['vCode']);
if ($xml->result->key->attributes()->type == 'Account'){
//If the 'type' of the returned API info is 'Account', continue.
foreach ($xml->result->key->rowset->row as $apiRow){
$charID = (int) $apiRow->attributes()->characterID;
if ($charID == $api->getCharacterID($_POST['username'])){
//DO SOMETHING WITH INFO
}
else{
}
}
}
else{
}
}
else{
}
}
else{
}
}
else{
}
}
else{
}
Efficiency wise this isn't going to matter all that much, but for maintainability's sake it will.
Instead of nesting so many ifs like that, try early failure with your ifs. Something like this:
if ($api->getCharacterID($_POST['username']) == 0) {
// Fail early. Throw an exception, die, or whatever
}
// Continue along as normal, not in an else.
if ($_POST['email1'] != $_POST['email2']) {
// Fail early. Throw an exception, die, or whatever
}
// Etc.
That sort of strategy will generally serve you well unless there's a very good reason to not use it.
It is hard to read and not very clean. The way I do it is use negative if statements. By that I mean the following:
if ($api->getCharacterID($_POST['username']) == 0){
// Username is not valid, so stop execution
}
if ($_POST['password1'] != $_POST['password2']) {
// Send error to user and stop execution
}
// ...etc.
Now how do you stop execution? Well you have few options
Throw an exception
Use die statement
have a parameter that you change everytime you enter an if block, then check if you should continue.
some other solution
But the point is, this approache makes your code cleaner.
Cheers.
These days mostly programmer use jquery / Javascript for forms validations, but if you are using pure PHP the try below code, hope it will be good and secure obviously :)
$username = mysql_real_escape_string($_POST['username']);
if($username == "")
{
$username_required = '<div>Please enter your username</div>';
} else {
$username_ok = true;
}
Typically in most validation patterns out there they have this errors array where you check for all the conditions and add error messages into the array if the array is empty at the end it only means that there are no errors..
For me i wouldn't want my code to look too nested like this i would use variables to dictate each step.
From there you can decide whether to display just the first error. It doesnt hurt to validate through everything at once because the processing should not be that extensive unless you have like 5000 form fields. I think it's ok.
When you code you must remember because code is written for humans and you will want to be kind to your eyes or for those who read your code.. Basically nested is ok. it saves some further processing and it also depends on the logic you need.
Yes its good to save time but at times you do things too nicely to minimize processing you have to weigh the needs if you do it so nice but in the end the time you save is so substantial then it makes no point.. The compiler is not going to pat your back and say good job anyways..
$errors = array();
$usernameValid = $api->getCharacterID($_POST['username']) != 0;
if (!$usernameValid) $errors[] = 'Username is not valid';
//If you want to store which attribute caused the error you can use the attribute name as array key
//if (!$usernameValid) $errors['username'] = 'Username is not valid';
$passwordMatches = $_POST['password1'] == $_POST['password2'];
if (!$passwordMatches) $errors[] = 'Password does not match';
if ($usernameValid && $passwordMatches)
{
//What to do if user name and password passes validation. wooo hoo~
}
//Etc etc..

How can I check a form POST only contains letters on multiple fields using preg_match?

I have this current code that allows me to check the users first name from a registration form to ensure it only contains letters, spaces and dashes. However how can I enable checking multiple fields (e.g. last name too).
/* Checks if the first name only includes letters, dashes or spaces */
if(preg_match("/^[a-zA-Z -]+$/", $_POST['firstname']) == 0)
$errors .="Your name must only include letters, dashes, or spaces.";
I've tried the following but it seems to only check one or the other, not both.
if(preg_match("/^[a-zA-Z -]+$/", $_POST['firstname'], $_POST['lastname']) == 0)
and also:
if(preg_match("/^[a-zA-Z -]+$/", $_POST['firstname'] and $_POST['lastname']) == 0)
Thanks in advance for any suggestions.
Since both of the fields are going to be validated with the same regex and you don't want to return any specific feedback about which one, if any, fails you can simply concatenate the two strings.
if(preg_match("/^[a-zA-Z -]+$/", $_POST['firstname'] . $_POST['lastname']) == 0)
You can use preg_grep, which is preg_match for arrays.
$results = preg_grep('/[^a-zA-Z -]/', $_POST);
if (count($results) > 0) {
die("Some field has invalid characters");
}
But, as AurimasL has pointed out above, you'd probably want to validate each field individually, so you can give better feed back instead of just a blanket "You screwed up, fix it!" error.
Of course, nothing says you can't use this preg_grep as a quick/dirty check for ANY errors, then do individual field checks in case there ARE errors.
You can do this kind of thing using preg_match but it is a very dirty thing because you will never know what is the field that don't respect your rules. You can concatenate the strings like the example:
if(preg_match("/^[a-zA-Z -]+$/", $_POST['firstname'] . $_POST['lastname']) == 0)
Anyway I suggest you to check every field individually and not do this kind of things.
Validate each field
if (preg_match("/^[a-zA-Z\s-]+$/i", $_POST['firstname']) == 0) {
$errors .="Your name must only include letters, dashes, or spaces.";
}
if(preg_match("/^[a-zA-Z\s-]+$/i", $_POST['lastname']) == 0) {
$errors .="Your lastname must only include letters, dashes, or spaces.";
}
Or Both (if user firstname and lastname separated by space)
if(preg_match("/^([a-zA-Z\s-]+)\s+([a-zA-Z\s-]+)$/i",$_POST['lastname'] . $_POST['lastname']) == 0) {
}
The solution to your problem is called: copy and pasting.
You need two if checks, or at least two conditions. You cannot pass two parameters to check onto preg_match.
That's the notation style I would advise you (even if I get some flak for that):
if ( preg_match("/^[a-zA-Z -]+$/", $_POST['firstname'])
and preg_match("/^[a-zA-Z -]+$/", $_POST['lastname']) )
{
...
}
It's important to note that the parenthesis have to be closed around each preg_match(...) call. The outer parens for the if() should stand out. If you are new to the language you should be diligent with formatting.
If you wanted to check for the not matching condition, then preface each preg_match() call with a ! NOT rather.

class design - validating user input

I use the clas below to validate user input. Originally it was just a collection of static functions grouped together.
However, I modifed it to an object style and added in a private memeber to hold the user input array. What is the next step to making this class adaptable, i.e. more generic so that it can be used by others as part of a library?
$message is the text displayed to the user on a validation fail.
Library Code:
class validate
{
private $input;
function __construct($input_arg)
{
$this->input=$input_arg;
}
function empty_user($message)
{
if((int)!in_array('',$this->input,TRUE)) return 1;
echo $message;return 0;
}
function name($message)
{
if(preg_match('/^[a-zA-Z-\.]{1,40}$/',$this->input['name'])) return 1;
echo $message;return 0;
}
function email($message)
{
if(preg_match('/^[a-zA-Z0-9._s-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{1,4}$/',$this->input['email'])) return 1;
echo $message;return 0;
}
function pass($message)
{
if(preg_match('/^[a-zA-Z0-9!##$%^&*]{6,20}$/',$this->input['pass'])) return 1;
echo $message;return 0;
}
}
Application Code:
function __construct()
{
parent::__construct();
$obj=check_new($this->_protected_arr);
$a='<si_f>Please enter both an email and a password!';
$b='<si_f>Please enter a valid email!';
$c='<si_f>Please enter a valid password!';
if($obj->empty_user($a) && $obj->email($b) && $obj->pass($c) && self::validate())
{
self::activate_session();
echo "<si_p>";
}
}
I'd not write all these function in a generic class. I'd rather have separate functions that perform specific checks, and maybe a specific class that calls these checks on my specific input.
This class now echo's, which is never a good solution for a class like this. Just let it perform the check and raise an exception if something's wrong. If exceptions are too hard, or don't fit in your achitecture, let your function return false, and set a property that can be read afterwards.
About your specific checks:
Your e-mail check is very strict and doesn't allow all e-mail addresses. The domain, for instance, can be an IP address too, and the username (the part before the #) can include many obscure characters, including an #. Yes, really!
Why must a password be 6 characters at least? And why on earth would you limit the password to 20 characters? I use passwords of over 20 characters, and I know many other people that do too. Just let everybody type everything they want. Anything. Let them post 3MB of text if they like. Let them include unicode characters if they want. What is a better protection that having a bunch of chinese characters as a password? And if they want to enter just a, that's their responsibility too.
You should never ever store the password itself anyway, so just hash whatever they input and store the 32 characters that gives you (if you use MD5 hashing). The only password that you may refuse is an empty password. Anything else should go.
Same goes for name. 40 characters? Really. I can imagine people having names that long. Add a little more space. Bytes aren't that expensive, and it's not that you're gonna have 2 billion users.
Maybe it's worth having a look at Zend Validate? Or any other PHP frameworks validate classes. Just then extend them to add the functionality you want.
In answer to your question, is it worth having another variable in the class so you can check the error?
class validate
{
private $input;
public $error = false;
function __construct($input_arg)
{
$this->input=$input_arg;
}
function empty_user($message)
{
if((int)!in_array('',$this->input,TRUE)) return 1;
echo $message;$this->error = "Empty message";
}
... else
}
$validate = new validate($empty_message);
if( !$validate->empty_user('this input is empty') === false)
{
echo "Was not empty";
}

Categories