[eluser]zimco[/eluser]
I'm trying to create the most basic login area for my application: one admin user and password stored in a mysql table.
I tried following the tutorial by Alex Biddle that uses Erkanaauth but i've mucked it all up and can't get it to work.
Can someone tell me what i am doing wrong and how to fix it?
File locations:
application/libraries/Erkanaauth.php
application/helpers/erkanaauth_helper.php
application/controllers/admin/authcontroller.php
application/controllers/admin/login.php
application/views/admin/content-login.php
The mysql table was created with the following command:
CREATE TABLE `users` (
`id` smallint(5) UNSIGNED NOT NULL AUTO_INCREMENT,
`username` varchar(10) NOT NULL,
`password` varchar(10) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
);
The admin user was inserted into the database with
INSERT INTO users (username, password) VALUES ("admin", sha1("demo"));
Here's the code for my login.php controller:
Code: <?php
class Login extends Controller
{
function Login()
{
parent::Controller();
$this->base = $this->config->item('base_url');
$this->css = $this->config->item('css');
$this->load->library('validation');
$this->load->helper('form');
$this->load->library('Erkanaauth');
}
/*======================================================================*\
Function: index()
Purpose: Provide the Login entry page.
Input:
Output: Display login page view
\*======================================================================*/
function index()
{
$login_form_rules = array
(
'username' => 'callback_check_username',
'password' => 'required'
);
$login_form_fields = array
(
'username' => 'username',
'password' => 'password'
);
$this->validation->set_fields($login_form_fields);
$this->validation->set_rules($login_form_rules);
if ($this->validation->run() == FALSE)
{
//Load the view file
$data['css'] = $this->css;
$data['base'] = $this->base;
// set the header view
$data['header'] = $this->load->view('header', '');
// set the page content
$data['content'] = $this->load->view('admin/content-login', $data);
// set the footer view
$data['footer'] = $this->load->view('footer', '');
}
else
{
redirect('admin/success');
}
}
/*======================================================================*\
Function: check_username($username)
Purpose:
Input:
Output:
\*======================================================================*/
function check_username($username)
{
$this->load->helper('security');
$password = dohash($this->input->post('password'));
if ($this->erkanaauth->try_login(array('username' => $username, 'password' => $password)))
{
return True;
}
else
{
$this->validation->set_message('check_username', 'Incorrect login info.');
return False;
}
}
/*======================================================================*\
END
\*======================================================================*/
}
?>
Here's the code for my login view, content-login.php:
Code: <div id="content">
<div id="loginform">
<h1>Login</h1>
<?php echo $this->validation->error_string; ?>
<?php $attributes = array('id' => 'login'); ?>
<?php echo form_open('admin/index', $attributes); ?>
<p>
<label for="username">Username: </label>
<?php
$username = array(
'username' => 'username',
'maxlength' => '10',
'size' => '25',
);
echo form_input($username);
?>
<p>
<label for="password">Password: </label>
<?php
$password = array(
'password' => 'password',
'maxlength' => '10',
'size' => '25',
);
echo form_input($password);
?>
</p>
<p>
<?php echo form_submit('submit', 'Submit'); ?>
</p>
<?php echo form_close(); ?>
</div>
</div>
[eluser]ontguy[/eluser]
Nothing stands out. Is giving an error or the login just doesn't work?
[eluser]zimco[/eluser]
It's like the input is never being processed: you can type anything in username and password or leave them completely blank and it always goes to admin/index and produces a 404 Page Not Found The page you requested was not found, instead of outputting a validation error msg or returning me to the login page.
[eluser]ontguy[/eluser]
Code: $username = array(
'username' => 'username',
'maxlength' => '10',
'size' => '25',
);
should be the following, to give the input a proper name and adding the validated value in case of an error:
Code: $username = array(
'name' => 'username',
'value' => $this->validation->username,
'maxlength' => '10',
'size' => '25',
);
Is admin/index the uri that loads the admin login?
Do the views header.php and footer.php exists?
Is a particular reason you are assigning the view to a variable when it is not setup to return a string; it maybe functionality you'll add in the future?
Code: $data['header'] = $this->load->view('header', '');
[eluser]Alex Biddle[/eluser]
I think the problem is with the routing, try adding this to your routes.php config file:
Code: $route['admin/login'] = 'admin/login';
Also I think you need to change
Code: <?php echo form_open('admin/index', $attributes); ?>
to
Code: <?php echo form_open('admin/login', $attributes); ?>
[eluser]zimco[/eluser]
Thanks for all the responses it is closer to working now, I changed the form_open statement as suggested to: Code: <?php echo form_open('admin/login', $attributes); ?>
That at least got it to start sending validation error messages, but now whatever i type in the password field results in the error The password field must have a value. even if i give it the correct value or anything else.
I'll keep working on it this weekend and report back.
Thanks for all the help the CodeIgniter community is the best!
[eluser]ontguy[/eluser]
In the view, this:
Code: $password = array(
'password' => 'password',
'maxlength' => '10',
'size' => '25',
);
echo form_input($password);
should be:
Code: $password = array(
'name' => 'password',
'maxlength' => '10',
'size' => '25',
);
echo form_password($password);
[eluser]zimco[/eluser]
I finally solved my login problems, but it was not easy. Besides the errors that people already pointed out as posted above there were errors that were not quite so obvious:
the copy of Erkanaauth that i had downloaded via the link posted in this forum thread was old and used getwhere(), which has been deprecated, so i had to replace all those calls to the new get_where, but the most irratating error was the fact that i created my table as posted above with: Code: `password` varchar(10) NOT NULL
Guess what happens when you SHA1 your password and insert it into the database? It's longer than 10 characters, but gets put into the database with just the first ten characters, so when you go to check for the dohash(password) it will never match (my-DUH moment)! Once i changed the password field to be long enough for a hashed password (`password` varchar(128) NOT NULL) it worked as expected.
Thanks for everybodies help and i've posted my finished working code below in hopes that it will help others learning to code a login box. FYI, i changed the name of my controller and view to sentry.php and content-sentry.php
I added an encryption key to my password by following Elliot Haughin's instructions and adding his _prep_password($password) function to the end of Erkanaauth which i will paste below too. Open-up your applications config.php file find and add a set of random numbers and letters at least 32 chararcters long:
Code: $config['encryption_key'] = "";
Remember to change your users database password field to the password.encrypted value.
Here's the code for my login controller, named sentry.php
Code: <?php
class Sentry extends Controller
{
function Sentry()
{
parent::Controller();
$this->base = $this->config->item('base_url');
$this->css = $this->config->item('css');
$this->load->library('validation');
$this->load->helper('form','security');
$this->load->library('Erkanaauth');
}
/*======================================================================*\
Function: index()
Purpose: Provide the Login entry page.
Input:
Output: Display login page view
\*======================================================================*/
function index()
{
$this->load->helper(array('form', 'url'));
$this->load->library('validation');
//$rules['username'] = "trim|required|min_length[5]|max_length[10]|xss_clean";
$rules['username'] = "callback_check_username";
$rules['password'] = "trim|required";
$this->validation->set_rules($rules);
if ($this->validation->run() == FALSE)
{
//Load the view file
$data['css'] = $this->css;
$data['base'] = $this->base;
// set the header view
$data['header'] = $this->load->view('header', '');
// set the page content
$data['content'] = $this->load->view('admin/content-sentry', $data);
// set the footer view
$data['footer'] = $this->load->view('footer', '');
}
else
{
//Load the view file
$data['css'] = $this->css;
$data['base'] = $this->base;
// set the header view
$data['header'] = $this->load->view('header', '');
// set the page content
$data['content'] = $this->load->view('admin/content-success', $data);
// set the footer view
$data['footer'] = $this->load->view('footer', '');
}
}
/*======================================================================*\
Function: check_username($username)
Purpose:
Input:
Output:
\*======================================================================*/
function check_username($username)
{
$this->load->helper('security');
$password = dohash($this->input->post('password'));
if ($this->erkanaauth->try_login(array('username' => $username, 'password' => $password)))
{
return TRUE;
}
else
{
$this->validation->set_message('check_username', 'Incorrect login info.');
return FALSE;
}
}
/*======================================================================*\
END
\*======================================================================*/
}
?>
oops too long of a post will add more later....
[eluser]zimco[/eluser]
POST CONTINUED....
Here's the code for my login view, content-sentry.php
Code: <div id="content">
<div id="login">
<h1>Login</h1>
<div id="login_error">
<?php echo $this->validation->error_string; ?>
</div>
<?php $attributes = array('id' => 'login'); ?>
<?php echo form_open('admin/sentry', $attributes); ?>
<p>
<?php
echo form_label('Username: ', 'username');
$username = array(
'name' => 'username',
'maxlength' => '10',
'size' => '25',
);
echo form_input($username);
?>
</p>
<p>
<?php
echo form_label(' Password: ', 'username');
$password = array(
'name' => 'password',
'maxlength' => '10',
'size' => '25',
);
echo form_password($password);
?>
</p>
<div><input type="submit" value="Submit" /></div>
</form>
</div>
</div>
Here's my code for Erkanaauth.php
Code: <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class Erkanaauth {
var $CI;
function Erkanaauth() {
$this->CI =& get_instance();
log_message('debug', 'Authorization class initialized.');
$this->CI->load->database();
$this->CI->load->library('session');
$this->CI->load->library('encrypt');
$this->CI->load->helper('erkanaauth_helper');
}
/**
* Attempt to login using the given condition
*
* Accepts an associative array as input, containing login condition
* Example: $this->auth->try_login(array('email'=>$email, 'password'=>dohash($password)))
*
* @access public
* @param array login conditions
* @return boolean
*/
function try_login($condition = array()) {
$password = $condition['password'];
//Salt the password see http://www.haughin.com/2008/02/17/handling-passwords-in-codeigniter/
$condition['password'] = $this->_prep_password($password);
$this->CI->db->select('id');
$query = $this->CI->db->get_where('users', $condition, 1, 0);
if ($query->num_rows != 1) {
return FALSE;
} else {
$row = $query->row();
$this->CI->session->set_userdata(array('user_id'=>$row->id));
return TRUE;
}
}
/**
* Attempt to login using session stored information
*
* Example: $this->auth->try_session_login()
*
* @access public
* @return boolean
*/
function try_session_login() {
if ($this->CI->session->userdata('user_id')) {
$query = $this->CI->db->query('SELECT COUNT(*) AS total FROM users WHERE id = ' . $this->CI->session->userdata('user_id'));
$row = $query->row();
if ($row->total != 1) {
// Bad session - kill it
$this->logout();
return FALSE;
} else {
return TRUE;
}
} else {
return FALSE;
}
}
/**
* Logs a user out
*
* Example: $this->erkanaauth->logout()
*
* @access public
* @return void
*/
function logout() {
$this->CI->session->set_userdata(array('user_id'=>FALSE));
}
/**
* Returns a field from the user's table for the logged in user
*
* Example: $this->erkanaauth->getField('username')
*
* @access public
* @param string field to return
* @return string
*/
function getField($field = '') {
$this->CI->db->select($field);
$query = $this->CI->db->get_where('users', array('id'=>$this->CI->session->userdata('user_id')), 1, 0);
if ($query->num_rows() == 1) {
$row = $query->row();
return $row->$field;
}
}
/**
* Returns the user's role
*
* Example: $this->erkanaauth->getRole()
*
* @access public
* @return string
*/
function getRole() {
$this->CI->db->select('roles.name');
$this->CI->db->JOIN('roles', 'users.role_id = roles.id');
$query = $this->CI->db->get_where('users', array('users.id'=>$this->CI->session->userdata('user_id')), 1, 0);
if ($query->num_rows() == 1) {
$row = $query->row();
return $row->name;
}
}
/*======================================================================*\
Function: _prep_password($password)
Purpose: Salt the password with an encryption key
Input: password string
Output: password string plus encryption key
\*======================================================================*/
function _prep_password($password)
{
$mykey = sha1($password.$this->CI->config->item('encryption_key'));
return $mykey;
}
/*======================================================================*\
END
\*======================================================================*/
}
?>
|