I’ve discovered a really annoying video tutorial by nettuts, but it gets the job done. just be glad you don’t have to listen to the annoying voice over. if you really want to bash your ears, find the video here
First thing is to create a new Controller called admin.
1. In application/controllers, create a file called admin.php. in this file, add the following code:
<?php if( !defined('BASEPATH')) exit('No direct script access allowed');
class Admin extends CI_Controller
{
public function index()
{
$this->load->view('v_login');
}
}
?>
2. Now you need to create the view for the login screen. In the view folder, create a file called v_login.php. insert some html code here to display your login UI. the tutorial suggested the code below:
<html lang="en">
<head>
<meta charset="utf-8">
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<?php echo form_open('admin'); ?>
<p>
<?php echo form_label('Username', 'username' ); ?>
<?php echo form_input('username', '', 'id="username"'); ?>
</p>
<p>
<?php echo form_label('Password', 'password' ); ?>
<?php echo form_password('password', '', 'id="password"'); ?>
</p>
<p>
<?php echo form_submit('submit', 'Login'); ?>
</p>
<?php echo form_close(); ?>
</body>
</html>
3. You need to alter the CodeIgniter autoload config. Open config/autoload and find the ‘libraries’ object and add ‘databases’ to it like so
$autoload['libraries'] = array('database');
also add url and form helpers by finding the helpers object and as follows:
$autoload['helper'] = array('url', 'form');
4. The next step is to add some validation so modify the admin controller and add the following code in the index function
$this->load->library('form_validation');
$this->form_validation->set_rules('username', 'Username', 'required|valid_email');
$this->form_validation->set_rules('password', 'Password', 'required');
if ( $this->form_validation->run() != false )
{
// validation pass
}
You’ll also need to add the markup for the validation error in your login view.
<div class="error"><?php echo validation_errors(); ?></div>
5. next up is the database. you’ll need to create a new one however you prefer. i’ll use phpmyadmin. i’ve created an auto incrementing id field, a username field, password field, first and last name fields and a created field. a note when creating a timestamp field, do not enter a length for the field, phpmyadmin doesn’t like it. Once that’s done, manually enter one user into the db.
6. now you need a model for your controller to connect to. create a file in the application/models directory called m_admin.php and insert the following code:
<?php
class M_Admin extends CI_Model
{
function __contruct()
{
}
public function verify_user( $username, $password )
{
$query = $this->db->where( 'username', $username )->where( 'password', sha1($password) )->limit(1)->get('users');
if ( $query->num_rows > 0 )
{
echo '<pre>';
print_r($query->row());
echo '</pre>';
return $query->row();
}
else
{
//error or empty
}
}
}
?>
7. now head back to the admin controller and load the model in by adding the following code: (swap the username and password out for your one)
$this->load->model('m_admin');
$this->m_admin->verify_user( 'username here', 'password here' );
8. you’ll need to alter the default database config in CodeIgnitor for this code to work. so open the database.php in the config directory and enter your database details. give it a test and it should spit out the first row from the db.
more to come soon…it’s bed time!
ok i’m back. so the next step is to take the actual user input. this is the same as using good ol $_POST.
9. replace the hard-coded username and password in the controller with $this->input->post(‘username’) and $this->input->post(‘password’) so the final line is
$this->m_admin->verify_user( $this->input->post('username'), ( $this->input->post('password') ) );
10. updating some config stuff. now this video changes the base url now which is something that should be done at the start. find the line that reads base_url and copy the root of your web site url into it. i’ll also change some security settings.
- xss should be set to true. this filters dodgy hacks from POST, GET and COOKIE data
- csrf should also be set to true. this helps prevent attacks that use image tags to conduc http requests to trusted websites
11. Next in the video, they store the logged in username into a session variable, except instead of using CodeIgniter for this, they use the php SESSION variable. strange. so i’ll use the CodeIgniter method instead.
first load the library using the following command in the constructor:
public function __construct()
{
parent::__construct();
$this->load->library('session');
}
you’ll also need to modify the config and add your own encryption key. this should be a 32 character (256-bit) string made up of letters and numbers.
to store a custom entry into the session, in this case the username, do the following:
$this->session->set_userdata('username', $this->input->post('username') );
finally, redirect to the secure page using redirect(‘welcome’)
12. now for a bit of fanciness, i’ll make it so the username field retains the value you entered if you enter an incorrect password. simply open the view class and change form_input for username to have a second parameter of set_value(‘username’).
13. a logout function would be good so use the following code:
public function logout()
{
$this->session->sess_destroy();
$this->load->view('v_login');
}
so now there is a logout function ready for a button to call it.
14. now is a good time to modify the config to load the login page by default. open the routes file in the config folder and set the default controller to admin.
15. now i’ll make sure that only logged in users can access the welcome page. add a constructor and the following code:
public function __construct()
{
parent::__construct();
$this->load->library('session');
if ( !$this->session->userdata('username') )
{
redirect( 'admin' );
}
}
it’s probably a good idea to add this functionality to the login page as well so if you are already logged in, just redirect to the welcome page.
16. now i’ll move the auth check into a library file so it can be reused across lots of controllers. create a library file called authenticate.php and paste the following code:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Authenticate
{
public function checkLoggedIn()
{
$CI =& get_instance();
$CI->load->library('session');
if ( !$CI->session->userdata('username') )
{
redirect( 'admin' );
}
}
}
now in each secure controller you just use the following two lines in the constructor:
$this->load->library('authenticate');
$this->authenticate->checkLoggedIn();
17. cleaning up the url. this should be done first really. once i’ve had some sleep i’ll tidy up this tutorial. create a .htaccess file in the root of your ci install. this is quite tricky in windows as it doesn’t like .htaccess files but the quick work around is to copy the .htaccess from the ci application directory. paste the following rewrite code:
RewriteEngine on
RewriteCond $1 !^(index\.php!resources!robots\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
now you don’t need the index.php in the url. you should also go into the config file and remove the index.php. just leave it blank. lastly i added a pretty url called logout so i don’t need to type admin/logout. i did this inside the routes file by adding the line:
$route['logout'] = 'admin/logout';
that’s it! again thanks to nettuts (even if the video was really annoying!) next up will be creating various user input modules for the CMS like text and images.
EDIT:
I discovered a new problem. after you logout you can still get back into the secure area by using the browser back button due to caching. luckily it’s very easy to fix. put this line inside your secure constructors:
$this->output->set_header("Cache-Control: no-store, no-cache, must-revalidate");