Panel Admina jest praktycznie gotowy, brakuje jednak kluczowej opcji - ograniczenia dostępu. Musimy stworzyć prosty mechanizm logowania dla admina. Jako że CI zabija również tablicę $_SERVER nie możemy skorzystać z autoryzacji HTTP (z którą i tak są kłopoty na niektórych serwerach). Skorzystamy z ciasteczek.
Do kontrolera Admin dodajemy metody:
function _check_login()
{
IF($cookie = $this->input->cookie('cicookie', True))
{
IF($cookie == md5(sha1($this->login.$this->password.$this->input->ip_address())))
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
function login()
{
$data["login"] = array('name' => 'login');
$data['pass'] = array('name' => 'pass');
$rules['login'] = "required|max_length[100]|xss_clean";
$rules['pass'] = "required|max_length[100]|xss_clean";
$this->validation->set_rules($rules);
if ($this->validation->run() == FALSE)
{
$data['login']['value'] = $this->input->post('login');
$data['pass']['value'] = $this->input->post('pass');
$this->response['content'] = $this->load->view('login', $data, True);
}
else
{
IF(md5(sha1($this->login.$this->password.$this->input->ip_address())) == md5(sha1($this->input->post('login').$this->input->post('pass').$this->input->ip_address())))
{
setcookie("cicookie", md5(sha1($this->login.$this->password.$this->input->ip_address())), time()+172800, '/', '', '0');
$this->response['content'] = '<h1>Zalogowany</h1><META HTTP-EQUIV="Refresh" CONTENT="1; URL='.site_url('admin').'">';
}
else
{
$this->response['content'] = '<h1>Błąd logowania</h1><META HTTP-EQUIV="Refresh" CONTENT="1; URL='.site_url('admin').'">';
}
}
$this->load->view('index', $this->response);
}
function logout()
{
setcookie("cicookie", NULL, time()-172800, '/', '', '0');
header('Location: '.site_url('admin'));
}
Konstruktor modyfikujemy do postaci:
function Admin()
{
parent::Controller();
$this->response = array();
$this->password = 'Rychu13';
$this->login = 'Rysiek';
IF(!Admin::_check_login() and $this->uri->segment(2) != 'login')
{
header('Location: '.site_url('admin/login'));
}
}
Metoda
_check_login() jest metodą "prywatną" (niedostępną poprzez URI) i sprawdza czy jesteśmy zalogowani. System opiera się na założeniu że:
- Stosujemy ciasteczko o nazwie "cicookie"
- Ciacho zawiera pewną daną określającą że admin to admin
- Dokładniej ciasteczko zawiera hasz z trzech zmiennych:
md5(sha1($this->input->post('login').$this->input->post('pass').$this->input->ip_address())
- loginu, hasła i adresu IP
- Hasz generowany przez md5 i sha1 to nieodkodowywalny łańcuch.
- Metoda
_check_login() porównuje hasz z ciasteczka z haszem otrzymanym z ustawionego loginu, hasła i bierzącego IP: jeżeli są takie same to jesteśmy "zalogowani"
Powyższy "system" logowania jest dość słaby. Chcąc stworzyć taki system z prawdziwego zdarzenia trzeba skorzystać z bazy danych i zapisywać np. znacznik czasu (time()) logowania oraz umieszczać je również w ciachu wewnątrz jakiegoś hasza, tak by przechwycenie ciasteczka przez inną osobę nic nie dało ("włamywacz" może "zmienić" swoje IP).
Metoda
login() to formularz z walidacją i utworzeniem ciacha jeżeli hasz danych z formularza zgadza się z haszem danych ustawionych w konstruktorze. Metoda
logout() wylogowuje. Szablon logowania:
<h1>Logowanie</h1>
<center><?=$this->validation->error_string; ?></center>
<?php echo form_open('admin/login'); ?>
<table width="90%" border="0" cellspacing="3" cellpadding="3">
<tr><td width="180"><B>Login</B></td><td><?php echo form_input($login); ?></td></tr>
<tr><td width="180"><B>Hasło</B></td><td><?php echo form_password($pass); ?></td></tr>
<tr><td> </td><td><?php echo form_submit('submit', 'Zapisz'); ?></td></tr>
</table>
<?php echo form_close(); ?>
<div class="rule"></div>
W
konstruktorze mamy
$this->password i
$this->login określające login i hasło. Następnie mamy:
IF(!Admin::_check_login() and $this->uri->segment(2) != 'login')
NazwaKlasy::metoda wywoła tą metodę wewnątrz klasy we wskazanym miejscu. Tutaj sprawdzamy zalogowanie. Jeżeli nie jesteśmy zalogowani i nie jesteśmy już na stronie logowania to przenoszeni jesteśmy na ową stronę logowania. Nie dostaniemy się na żadną stronę zależną od tego kontrolera bez zalogowania. Panel Admina zabezpieczony.
W widoku index.php obok linku "Główna" dodałem taki kod:
<?PHP
IF ($this->uri->segment(1) == 'admin' and $this->uri->segment(2) != 'login')
{
echo ' <li><a href="'.site_url('admin/logout').'" title="home">Wyloguj</a></li>';
}
?>
Jeżeli jesteśmy w panelu admina (/admin/*) i nie na stronie logowania to wyświetli się link "Wyloguj", który nas wyloguje i przeniesie na stronę logowania.