Can I set Ion auth to login by username OR Email

2019-06-28 06:04发布

问题:

I know I can set ion auth to login by username in the config, I also know I can set it to login by email in the config.

Is there a simple way to set it it to use either automatically?

回答1:

If by automatic, you mean try one and then the other to see if either gives a valid return:

The login occurs in ion_auth_model line: 899

->where($this->identity_column, $this->db->escape_str($identity))

so you could change this to do an "or" and try both columns. You would need to do this throughout the model because there is more than just the actual login to consider & there's the potential issue of a user having an email that is another user's username (however unlikely)



回答2:

Its possible with only a few code rows: Lets assume that this is your ion_auth config file:

$config['identity'] = 'username'; // A database column which is used to login with

you have to run the login function twice. If the first try (with username) didn't success, you can change the identifier and retry:

$this->ion_auth_model->identity_column = "email";

No modifications in model or library or custom querys neccesary



回答3:

I recently forked Ion Auth and made the necessary enhancements so that this could be chosen in the configuration. The fork is located here:

https://github.com/zepernick/CodeIgniter-Ion-Auth

I offered up a pull request to get this included in the Ion Auth code base, but it has not been accepted at this time. There was some debate going on about whether it made the code to complex. Please drop them a note and let them know you would like this functionality if it is useful to you.

https://github.com/benedmunds/CodeIgniter-Ion-Auth/pull/746



回答4:

without having to edit ion_auth_model, you can do something like this:

considering you already have this config:

 $config['identity'] = 'username';

and you have this on your controller:

// log the user in
public function login()
{
...
    if ($this->ion_auth->login($this->input->post('identity'), $this->input->post('password'), $remember))
    {
    //if the login is successful

you can let it to check and then if it's not successful, set the email as identity column and check for it:

// log the user in
public function login()
{
...

    // check for username
    $login = $this->ion_auth->login($this->input->post('identity'), $this->input->post('password'), $remember);
    if(! $login) { // username is not successful
        $this->ion_auth_model->identity_column = 'email';
        // check for email
        $login = $this->ion_auth->login($this->input->post('identity'), $this->input->post('password'), $remember);
    }

    if( $login ) {
         // successful
    } else {
         // both failed
    }

the advantage of this: more compatibility with any new update to ionAuth since you didn't change the core files. the downside of this is that's it's have to double query the database.


Auth controller code modified from: ionAuth Auth Controller Example

Discussions on ionAuth Repo:

  • Issue 510: Switching between username/email as identity
  • Issue 792: Login with Username or Email
  • Pull Request 746: Add option for alternate identity column


回答5:

use 'email' in 'identity' ion_auth config then add this code after $query in ion_auth_model line 866

if($query->num_rows() == 0){
    $query = $this->db->select($this->identity_column . ', username, email, id, password, active, last_login')
          ->where('username', $this->db->escape_str($identity))
          ->limit(1)
          ->get($this->tables['users']);
}


回答6:

I think the easier way would be checking if the $identity var is an email. If it's not an email, then you set the column to 'username'. Something like this:

$check_column = valid_email($identity) ? $this->identity_column : 'username';   
$query = $this->db->select('username, email, id, password, active, last_login')
    ->where($check_column, $this->db->escape_str($identity))
    ->limit(1)
    ->get($this->tables['users']);

In this case, you'll need the email_helper loaded.

Works for me.



回答7:

Put this on your Controller

if ($this->form_validation->run() !== FALSE) {
    $remember = (bool) $this->input->post('remember');
    $this->ion_auth_model->identity_column = 'username/email';

    if ($this->ion_auth->login($this->input->post('username'), $this->input->post('password'), $remember))
    {
        $this->session->set_flashdata('message', $this->ion_auth->messages());
    }
    redirect('auth/login');
}

Edit ion_auth_model.php. find the function login() and the update the code using the code below.

public function login($identity, $password, $remember=FALSE)
    {
        $this->trigger_events('pre_login');

        if (empty($identity) || empty($password))
        {
            $this->set_error('login_unsuccessful');
            return FALSE;
        }

        $this->trigger_events('extra_where');

        //just add this (starting this line)
        if ($this->identity_column == "username/email")
        {
            $fieldname = explode('/', $this->identity_column);
            $query = $this->db->select($fieldname[0] . ', username, email, id, password, active, last_login')
                          ->where($fieldname[0], $identity)
                          ->limit(1)
                          ->get($this->tables['users']);

            $this->identity_column = $fieldname[0];

            if ($query->num_rows() === 0) {
                $query = $this->db->select($fieldname[1] . ', username, email, id, password, active, last_login')
                          ->where($fieldname[1], $identity)
                          ->limit(1)
                          ->get($this->tables['users']);

                $this->identity_column = $fieldname[1];
            }
        }
        else
        {
            $query = $this->db->select($this->identity_column . ', username, email, id, password, active, last_login')
                          ->where($this->identity_column, $identity)
                          ->limit(1)
                          ->get($this->tables['users']);
        }
        //up to this line   

        if($this->is_time_locked_out($identity))
        {
            //Hash something anyway, just to take up time
            $this->hash_password($password);

            $this->trigger_events('post_login_unsuccessful');
            $this->set_error('login_timeout');

            return FALSE;
        }

        if ($query->num_rows() === 1)
        {
            $user = $query->row();

            $password = $this->hash_password_db($user->id, $password);

            if ($password === TRUE)
            {
                if ($user->active == 0)
                {
                    $this->trigger_events('post_login_unsuccessful');
                    $this->set_error('login_unsuccessful_not_active');

                    return FALSE;
                }

                $this->set_session($user);

                $this->update_last_login($user->id);

                $this->clear_login_attempts($identity);

                if ($remember && $this->config->item('remember_users', 'ion_auth'))
                {
                    $this->remember_user($user->id);
                }

                $this->trigger_events(array('post_login', 'post_login_successful'));
                $this->set_message('login_successful');

                return TRUE;
            }
        }

        //Hash something anyway, just to take up time
        $this->hash_password($password);

        $this->increase_login_attempts($identity);

        $this->trigger_events('post_login_unsuccessful');
        $this->set_error('login_unsuccessful');

        return FALSE;
    }


回答8:

You can do this without modifying the core code. Just change the identity column on the fly if a valid email is present. NOTE: ion_auth_model not ion_auth.

public function check_login()
{
    if (!$this->input->is_ajax_request()) {
        exit('No direct script access allowed');
    }
    $this->form_validation->set_rules('username', str_replace(':', '', $this->lang->line('login_identity_label')), 'required');
    $this->form_validation->set_rules('password', str_replace(':', '', $this->lang->line('login_password_label')), 'required');
    if ($this->form_validation->run() == false) {
        $this->form_validation->json_errors();
    }
    $identity = $this->input->post('username');
    if ($this->form_validation->valid_email($identity)) {
        $this->ion_auth_model->identity_column = 'email';
    } else {
        $this->ion_auth_model->identity_column = 'username';
    }
    if ($this->ion_auth->login($identity, $this->input->post('password'), false)) {
        encode_response('success');
    } else {
        encode_response('error', $this->ion_auth->errors());
    }
}