7

I'd like to use form validation to require a password that has BOTH alpha and numeric characters. Here's what I've come up with so far:

$this->form_validation->set_rules('password', 'Password', 'required|matches[passconf]|min_length[8]|alpha_numeric');

The issue is that "alpha_numeric" requires that the password only contain letters or numbers, it doesn't require both. Going for the stronger password option here.

chowwy
  • 1,126
  • 8
  • 26
  • 45

3 Answers3

18

You could set up a callback in your controller:

public function password_check($str)
{
   if (preg_match('#[0-9]#', $str) && preg_match('#[a-zA-Z]#', $str)) {
     return TRUE;
   }
   return FALSE;
}

Then, update your rule to use it:

$this->form_validation->set_rules('password', 'Password', 'required|matches[passconf]|min_length[8]|alpha_numeric|callback_password_check');
rjz
  • 16,182
  • 3
  • 36
  • 35
15

An alternate solution that can be easily reused in other projects and localizes your validation rules is to extend the Form_validation class.

In application/libraries/ create a file called MY_Form_validation.php where 'MY' is your subclass prefix set in application/config/config.php.

The class would look something like:

class MY_Form_validation extends CI_Form_validation
{
    /**
     * Verify that a string contains a specified number of
     * uppercase, lowercase, and numbers.
     *
     * @access public
     *
     * @param String $str
     * @param String $format
     *
     * @return int
     */
    public function password_check($str, $format)
    {
        $ret = TRUE;

        list($uppercase, $lowercase, $number) = explode(',', $format);

        $str_uc = $this->count_uppercase($str);
        $str_lc = $this->count_lowercase($str);
        $str_num = $this->count_numbers($str);

        if ($str_uc < $uppercase) // lacking uppercase characters
        {
            $ret = FALSE;
            $this->set_message('password_check', 'Password must contain at least ' . $uppercase . ' uppercase characters.');
        }
        elseif ($str_lc < $lowercase) // lacking lowercase characters
        {
            $ret = FALSE;
            $this->set_message('password_check', 'Password must contain at least ' . $lowercase . ' lowercase characters.');
        }
        elseif ($str_num < $number) //  lacking numbers
        {
            $ret = FALSE;
            $this->set_message('password_check', 'Password must contain at least ' . $number . ' numbers characters.');
        }

        return $ret;
    }

    /**
     * count the number of times an expression appears in a string
     *
     * @access private
     *
     * @param String $str
     * @param String $exp
     *
     * @return int
     */
    private function count_occurrences($str, $exp)
    {
        $match = array();
        preg_match_all($exp, $str, $match);

        return count($match[0]);
    }

    /**
     * count the number of lowercase characters in a string
     *
     * @access private
     *
     * @param String $str
     *
     * @return int
     */
    private function count_lowercase($str)
    {
        return $this->count_occurrences($str, '/[a-z]/');
    }

    /**
     * count the number of uppercase characters in a string
     *
     * @access private
     *
     * @param String $str
     *
     * @return int
     */
    private function count_uppercase($str)
    {
        return $this->count_occurrences($str, '/[A-Z]/');
    }

    /**
     * count the number of numbers characters in a string
     *
     * @access private
     *
     * @param String $str
     *
     * @return int
     */
    private function count_numbers($str)
    {
        return $this->count_occurrences($str, '/[0-9]/');
    }
}

Then set the rule:

$this->form_validation->set_rules('password', 'Password', 'required|matches[passconf]|min_length[8]|alpha_numeric|password_check[1,1,1]');

The rule can be used in many different ways. 'password_check[1,1,1]' would require a password contain a lowercase, uppercase, and number character. 'password_check[5,0,1]' would require 5 uppercase characters and a number in the password.

The advantages of doing it this way are:

  1. All your rules are contained within an easily portable class
  2. Sub-validation functions such as 'count_occurences' can easily be used in other validation functions.
  3. The class can be modified to use language files in application/language/
None
  • 5,491
  • 1
  • 40
  • 51
  • Thanks for this very thorough answer; I'm upvoting it (since I already accepted another answer). Hopefully it will help future googlers. – chowwy May 16 '12 at 13:30
  • I just loved this function: Anyway I think you have to change list($username, $lowercase, $number) = explode(',', $format); to list($uppercase, $lowercase, $number) = explode(',', $format); – Rocks Apr 01 '14 at 03:14
  • this is really help full answer , I will add it into my blog . – Smoke Oct 26 '15 at 12:45
  • HI sir, I would like to ask how can I allow special character? – Angel Jul 11 '17 at 11:01
  • @Angel You would need to add a function that counts special characters, to update the `password_check` method so it uses that new function to check the string for enough special chars, and to modify the rule. If you get stuck open a new question. – None Aug 03 '17 at 19:21
-2

Using CI 2.2.0, there are parameters you can add, like the 'alpha_numeric' parameter, note the piped (cascaded) parameters:

function check_password(){
 $this -> form_validation -> set_rules('password', 'New Password', 'required|max_length[15]|min_length[6]|alpha_numeric');
 $this -> form_validation -> set_rules('passconf', 'Re-enter', 'required|matches[password]');

 if ($this -> form_validation -> run() == FALSE){
  doStuff();
 } else {
  doOtherStuff();
 }
}

Look for the Rule Reference near the bottom of this page.

b..
  • 97
  • 1
  • 5