Az adminisztrátori vagyis foglalás-menedzsment funkcionalitás eleve rejtve van a kíváncsi tekintetek elől, hiszen ha kint is van az Interneten, vagyis a “webtérben” az oldal, link nincs az admin oldalunkra a honlapon. Azonban ennél azért nagyobb biztonságra lesz szükségünk, ezért az egész admin funkcionalitást el kell rejtsük egy jelszóval védett területre.
A jelszavas védelmet a CodeIgniter keretrendszer alapban nem támogatja, viszont egyszerűen megvalósíthatjuk. Egyszerűen úgy működik, hogy a controller-ben a kívánt funkciók hívása előtt megvizsgáljuk, hogy előzőleg tároltunk-e el a szerver session-jében “user” változót a korábban lezajló login folyamat során, amelyben adatbázisban ellenőrizzük a felhasználó/jelszó párt. Van benne még technikailag pár átirányítás, hogy a webalkalmazásunk “visszataláljon” a “hívó” oldalra (referer) a sikeres jelszó hitelesítés (authentikáció) vagyis belépés (login) után.
És akkor most nézzük a konkrét implementációt.
Először is kell egy modell. Ez az models/Auth_model.php
file-unk. Összezsúfoltam picit a kódot – nem szokásom amúgy -, hogy minél kevesebb sorban oldjam meg a feladatot. 🙂
<?php
class Auth_model extends CI_Model {
public function login(){
$query = $this->db->get_where('users', array('name' => $this->input->post('username'), 'password' => $this->input->post('password')));
$result = $query->result();
return (empty($result)?false:(empty($result[0])?false:true));
}
}
Ez a login()
metódus egy boolean – logikai – értékkel tér vissza attól függően, hogy megvan-e az adatbázisban a felhasználó/jelszó páros. Pár technikai észrevétel: a felhasználónévnek egyedinek kell lenni (ezt egy ún. unique key vagyis egyedi kulcs bitosítja SQL technikában), hogy nyilvánvalóan különbözzenek a felhasználóink. A gyakorlatban általában az e-mail címeket választják ki a mérnökök erre a célra, hiszen az mindenképpen egyedi. 🙂 Aztán a jelszó. Nem kódoltam le ebben a pilot alkalmazásban, de illik valamilyen egyirányú kódoló algoritmussal titkosítani, hogy senki se fejthesse vissza a jelszavakat az adatbázis ismeretében. 🙂
Nézzük a meg views/login.php view-nkat.
<?php
$my_base_url = '/apartman/';
?>
<div class="row">
<div class="col-sm-2">
<div id="fh5co-logo"><a href="index.html">Apartman<span>.</span></a></div>
</div>
<div class="col-sm-10 text-right menu-1">
<ul>
<li><a href="photos"><?php echo $this->lang->line('menu_photos'); ?></a></li>
<li><a href="booking"><?php echo $this->lang->line('menu_booking'); ?></a></li>
<li><a href="contact"><?php echo $this->lang->line('menu_contact'); ?></a></li>
</ul>
</div>
</div>
</div>
</div>
</nav>
<div class="container">
<div id="fh5co-intro">
<div class="row animate-box">
<div class="col-md-8 col-md-offset-2 col-md-pull-2">
<h2><?php echo $this->lang->line('menu_booking'); ?></h2>
</div>
</div>
</div>
<div id="fh5co-contact">
<div class="row">
<div class="col-md-8 animate-box">
<div class="form-wrap">
<div class="row">
<form action="login" method="POST">
<?php if ($auth_errors) { ?>
<div class="col-md-12">
<div class="form-group">
<h3><font color="red"><?php echo $auth_errors; ?></font></h3>
</div>
</div>
<?php } ?>
<div class="col-md-12">
<div class="form-group">
<input type="text" name="username" class="form-control" placeholder="User Name">
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<input type="password" name="password" class="form-control" placeholder="Password">
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<input type="submit" value="Login" class="btn btn-primary btn-modify">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div><!-- END container -->
Ebben érdekes, hogy egy sima formot használunk, nem JavaScript-eset, és hogy password típusú mezőbe kérjük be a jelszót, amit nem lehet elolvasni a képernyőn, miközben begépeljük, csak pontokat látni a karakterek helyén. Ez a biztonságot szolgálja. Más kérdés, hogy a billentyűzetről is le tudja olvasni egy ügyes tekintetű illető a jelszót, úgyhogy ilyenkor illik “nem oda nézni” a harmadik félnek. 🙂
Majd nézzük a szintén nem túl bonyolult controller-ünket (controllers/AuthController.php
). Megjegyzem, hogy végre beállítottam a config/config.php => $config['base_url'] = 'http://localhost/apartman/';
értéket, hogy használhassam az a base_url($path)
metódust a redirect-ek (átirányítások) miatt. 🙂
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class AuthController extends CI_Controller {
public function __construct(){
parent::__construct();
}
public function is_logged($referer){
$user = $this->session->userdata('user');
if (empty($user)) {
// not authenticated
$this->session->set_userdata('login_url', $referer);
redirect(base_url('index.php/AuthController/login_form'));
}
}
public function login_form(){
$data = array();
$data['auth_errors'] = '';
if (!empty($this->session->flashdata('auth_errors'))) {
$data['auth_errors'] = $this->session->flashdata('auth_errors');
}
$this->template->set('title', 'Login');
$this->template->load('menu_layout', 'contents', 'login', $data);
}
public function login(){
$this->load->model('auth_model');
$success = $this->auth_model->login();
if ($success) {
$this->session->set_userdata('user', $this->input->post('username'));
redirect($this->session->userdata('login_url'));
} else {
// login fail
$this->session->set_flashdata('auth_errors', 'Login failed.');
redirect($_SERVER['HTTP_REFERER']);
}
}
public function logout(){
$this->session->set_userdata('login_url', null);
$this->session->set_userdata('user', null);
}
}
Látható, hogy három fontos metódust tartamaz. Az is_logged($referer)
gondoskodik arról, hogy megvizsgáljuk, van-e belépett felhasználó (user) a session-ben. A login_form()
hibaüzenetek kezelését, illetve a login form kirajzolását végzi, míg a login()
a tulajdonképpeni beléptetést a modellhívással. A logout() csak játék, technikailag vettem fel. Egyszerűen töröl minden session-ban tárolt változót.
Ezt a controller-t az alkalmazásunk fő vezérlőjében (controllers/Apartments.php
) az alábbi módon használjuk.
<?php
include APPPATH.'controllers/AuthController.php';
class Apartments extends AuthController {
public function admin() {
// check if user is authenticated
// config/config.php => $config['base_url'] = 'http://localhost/apartman/';
$this->is_logged(base_url('index.php/apartments/admin'));
$this->load->model('reservations_model');
$data['query'] = $this->reservations_model->get_reservations();
$this->template->set('title', 'Admin');
$this->template->load('menu_layout', 'contents' , 'admin', $data);
}
public function admin_approve_ajax($id) {
// check if user is authenticated
$this->is_logged(base_url('index.php/apartments/admin'));
$this->load->model('reservations_model');
$this->reservations_model->approve_reservation($id);
$data = $this->reservations_model->get_reservation($id)[0];
header('Content-Type: application/json');
echo json_encode($data);
}
}
Látható, hogy az AuthController
-t include-oljuk a kód elején, majd extends-szel alaposztályként hivatkozunk rá. Innentől egy is_logged($referer)
hívással mindkét adminisztrátori metódus legelején eldöntjük, hogy “be van-e lépve” az adminisztrátor. Ha nem, akkor átirányítjuk a login form-ra, ha igen, megy tovább a buli. 🙂
És akkor nézzük a login form-unkat! A http://localhost/apartman/index.php/AuthController/login_form webcím alatt látható, ha az admin oldalt szeretnénk megnyitni, és a session változó már elévült a webszerverünkön vagy netán kipróbáltuk a logout()
funkciót. 🙂
