Regex for password PHP

75,091

Solution 1

I find that doing it in one big regex is a bit of a code maintenance nightmare. Splitting it up is far easier to figure out for someone else looking at your code, and it allows you to give more specific error messages as well.

$uppercase = preg_match('@[A-Z]@', $password);
$lowercase = preg_match('@[a-z]@', $password);
$number    = preg_match('@[0-9]@', $password);

if(!$uppercase || !$lowercase || !$number || strlen($password) < 8) {
  // tell the user something went wrong
}

Solution 2

^\S*(?=\S{8,})(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[\d])\S*$

From the fine folks over at Zorched.

  • ^: anchored to beginning of string
  • \S*: any set of characters
  • (?=\S{8,}): of at least length 8
  • (?=\S*[a-z]): containing at least one lowercase letter
  • (?=\S*[A-Z]): and at least one uppercase letter
  • (?=\S*[\d]): and at least one number
  • $: anchored to the end of the string

To include special characters, just add (?=\S*[\W]), which is non-word characters.

Solution 3

One possible regex pattern is:

/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/

As in this example.

But you really shouldn't limit passwords!

enter image description here

Admit it. As a developer we have done more to contribute to the failure of our customer's and user's online security because we are too stubborn or lazy to handle passwords properly. Just look at some of the fruit of our labor:

Password must be between 5 and 32 characters in length. Valid characters include letters, numbers, and underscore.

Password must be between 6 and 12 characters in length. Valid characters include letters and numbers.

Password must be a minimum of 8 characters and contain at least one capital letter, a number and a special character such as an underscore or exclamation point.

Then there is this gem. The original requirements were a minimum of 8 characters. Accidentally putting in 7 characters causes an error to appear before the user:

enter image description here

Password Limitation Gone Wrong Note the tag line. Irony?

I could go on here, but I think you get the point. We have written code to support this nonsense, wrapping our heads around the right regex to account for every case. Agonizing over transmission, hashing and storage. We've talked about this so much the situation has even received proper pop culture status with its memorialization on xkcd.

There is no doubt our intentions were good. After all, users and customers cannot be expected to protect themselves properly. They don't create strong passwords, they use the word 'password' as their password more often than not. They don't heed the warnings, the news stories or the horror exrpressed by friends who have suffered through identity theft. The hacking of large retail chains phases them very little. We, as developers, set out to help our users avoid these pitfalls. I will alledge our attempts fell short and may have even contributed to the problem.

Very likely we've made it worse.

By placing arcane restrictions on passwords we have actually forced our users into a bad way of thinking and therefore made them seek the path of least resistance, simple, hackable passwords. We did this because we were used to restrictions on us. Sysadmins limited us to 8 characters so we projected the limit on to the rest of the world. It is time we stopped and learned how to handle any length of password with any character included. We may want to exclude white spaces from the password, but other than that we shouldn't place any restrictions on passwords.

Then we can encourage good security practices like passphrases or random words. Users, once they discover this, will be blissfully happy they don't have to remember some goofy combination of letters and numbers like f@rtp00p.

I can see you rolling your eyes. It means you have to learn how to properly hash passwords and how to compare entered passwords with the hashes. You'll have to toss some really hard won regex. Heaven forbid you might have to refactor some code! Databases can hold very large hashed passwords and we should take advantage of the capability.

Keep in mind the general security of the data is on me, the developer along with the sysadmin and others. The security of a user's account is on them and I shouldn't do anything to hold them back. Personally I do not care what my users have for their passwords. All I do when users create their passwords is provide a strength meter and some basic guidelines:

"We have found using passphrases or multiple word combinations to be the most secure when it comes to preventing a hacker, who is trying to crack your login information, from being successful."

What should you do?

PHP's built-in functions handle password security perfectly, spaces, special characters and all.. If you're using a PHP version less than 5.5 you can use the password_hash() compatibility pack.

We need to remove the limitations on passwords and free up the users to own their security online. Are you in?

Solution 4

PHP regular expression for strong password validation

The link above looks like the regex you want. You could try something like the code below:

if(preg_match((?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$), $_POST['password']):

echo 'matched';

else:

echo 'not matched';

endif;
Share:
75,091
Peter Stuart
Author by

Peter Stuart

My name is Peter. I am a web developer always seeking to learn and grow in my graft. I'm usually asking more than answering on here, but will help where and when I can

Updated on July 20, 2020

Comments

  • Peter Stuart
    Peter Stuart almost 4 years

    I found a script online and it has a password regex in JavaScript. I still want to use it, but for more security I want to use PHP to validate my password too but I'm useless with regex.

    The requirements:

    • Must be a minimum of 8 characters
    • Must contain at least 1 number
    • Must contain at least one uppercase character
    • Must contain at least one lowercase character

    How can I construct a regex string to meet these requirements?

  • Peter Stuart
    Peter Stuart over 12 years
    Sorry, I forgot to add, how do I prevent special characters too? Thanks
  • ceejayoz
    ceejayoz over 12 years
    You shouldn't prevent special characters. They help make passwords more secure.
  • Peter Stuart
    Peter Stuart over 12 years
    Okay thanks, I suppose thats true:)
  • Alex Turpin
    Alex Turpin over 12 years
    +1 for the explanation of it's various parts. More people need to do this in their answers.
  • rybo111
    rybo111 about 10 years
    @pcperini's answer seems to be getting more upvotes, but this approach makes it very easy to tell the user what their password is missing, rather than having to list everything required in the password.
  • user_vgizy
    user_vgizy over 9 years
    if (preg_match("/[^\S*(?=\S{8,})(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[‌​\d])\S*$]/",$name)){ OK} else{error} is it correct?
  • pal4life
    pal4life over 9 years
    Hi, This is different than the pattern showed above, like it begins with ?= rather than \S, any specific reason for that?
  • Will B.
    Will B. almost 8 years
    If it was a perfect world, end-users would already be security-centric. The idea of someone guessing an easy password originated from real-life occurrences, but I agree, passwords are not the issue. You should provide some info on methodologies that developers can implement to prevent end-user password cracking. Such as brute-force prevention, captcha, two-factor authentication, csrf-tokens, ip-address tracking/notification, region tracking/blacklisting, OpenID authentication, password expiration, registration verification, etc.
  • Alan Moore
    Alan Moore almost 8 years
    The leading \S* is superfluous. It doesn't actually break the regex, but it makes no sense there; all it does is make the regex much less efficient. SO user ridgerunner explained in more detail in his comments under the Zorched article.
  • Alan Moore
    Alan Moore almost 8 years
    @pal4life: the leading \S* in Patrick's answer is incorrect, as I explained in a comment on that answer. This answer has many problems, but that isn't one of them.
  • Fi Horan
    Fi Horan over 7 years
    @ceejayoz made me laugh. I really like how simplistic the approach is and like rybo111 said it makes it much easier to let the user know what they've done wrong. Though this should only catch something if someone has tampered with the jquery validation.
  • Sparw
    Sparw over 7 years
    Thank you so much ! :)
  • Parapluie
    Parapluie about 7 years
    Great answer, @ceejayoz. I just want add, in case anyone IS looking to match special characters as well, deejay's code can be modified thus: $specialChars = preg_match('@[^\w]@', $password);
  • publicknowledge
    publicknowledge over 5 years
    pretty useful. better than regexing stuff and forgetting what and how it works months later.
  • Peter Stuart
    Peter Stuart about 2 years
    Im terribly sorry it's taken me 7 years to even read this answer! Thanks for the input and effort. I really appreciate it