Kto przebrnal przez system logowania Acl cake oraz moze kilka innych i potrawi z powodzeniem zaimplementowac to we wlasnym zakresie …szacun. ja nie
. Dlatego przedstawiam dosc indywidualne rozwiazanie systemu logwania i uwierzytelniania.
Zacznijmy od bazy. Potrzebujemy 2 tabele w bazie danych
groups – przechowuje prawa poszczegolnych grup uzytkownikow. Ponizej struktura..
CREATE TABLE groups (
id int(3) NOT NULL auto_increment,
group_name varchar(50) character set latin1 default NULL,
level int(5) default NULL,
cake tinyint(1) NOT NULL default '0',
debug tinyint(1) NOT NULL default '0',
przekierujPoZalogowaniu varchar(250) character set latin1 NOT NULL default '/',
modified datetime NOT NULL,
created datetime NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
- group_name – przechowywujemy tutaj nazwy grup userow, np. Klient, Admin, Super Admin
- level – poziom jakie dana grupa posiada
- cake – pzyjmuje wartosci 0 lub 1…w dalszej czesci bedzie to dokladniej wyjasnione
- debug – jaki debug ma byc wlaczony dla danej grupy po zalogowaniu (przydatne jezeli logujemy sie jako Super Admin i chcemy miec debug = 2)
- przekierujPoZalogowaniu – miejsce gdzie przekierowujemy usera po zalogowaniu np. Admin => ‘/admin’ , Klient => /users/myaccount
users – tabel w ktorej przechowywujemy dane dostepowe do systemu
CREATE TABLE users (
id int(7) unsigned NOT NULL auto_increment,
userName varchar(50) NOT NULL,
passwd varchar(32) NOT NULL,
name varchar(50) NOT NULL,
email varchar(100) NOT NULL,
lastVisit datetime default '0000-00-00 00:00:00',
group_id int(10) unsigned NOT NULL default '0',
active tinyint(1) unsigned NOT NULL default '0',
created datetime NOT NULL default '0000-00-00 00:00:00',
modified datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (id),
UNIQUE KEY username (userName),
UNIQUE KEY email (email,userName),
KEY group_id (group_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- userName – nazwa robocza usera np. juby
- email – nasz login
- lastVisit – mozemy wykorzystac do statystyk kiedy, kto sie zalogowal
- group_id – bardzo wazna czesc tabeli, tutaj podajemy group_id jaki posiadac bedzie dany user, np. jezeli w tabeli ‘groups’ pod id = 1 bedziemy przechowywac Super Admina to wpisujac tutaj 1 pokazujemy ze dany user ma byc Super Adminem
- active – mozemy wykorzystac w celu sprawdzenia czy dane konto jest aktywne lub nie (0 – nie, 1- tak)
nastepnie tworzymy modele z nstp relacjami
group.php
class Group extends AppModel
{
var $name = 'Group';
var $hasMany = 'User';
}
oraz user.php
class User extends AppModel {
var $name = 'User';
var $belongsTo = array(
'Group' => array('className' => 'Group',
'foreignKey' => 'group_id'
)
);
Zalozmy ze w tablicy ‘groups’ bedziemy miec nstp. grupy userow
INSERT INTO `groups` (
`id`, `group_name`, `cake`, `debug`, `przekierujPoZalogowaniu`, `modified`, `created`) VALUES
(1, 'Super Admin', 1, 2, '/admin/home', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(2, 'Admin', 1, 0, '/admin/home', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(3, 'Klient', 0, 0, '/', '0000-00-00 00:00:00', '0000-00-00 00:00:00');
jezeli mamy juz utworzone modele oraz tabele czas na app_controller.php. Oto kilka rzeczy, ktore musimy w nim wykonac.
//app_controller.php
// miejsce formularza z logowaniem, bedzie nam potrzebny controller 'users_controller.php'
var $loginForm = "/users/login";
function beforeFilter()
{
// w funkcji tej sprawdzamy czy przypadkiem w adresie nie ma Routing.admin....jezeli jest wywolujemy funckje restrictAccess(1)
if (isset($this->params[Configure::read('Routing.admin')])) {
$this->restrictAccess(1);
}
}
function beforeRender()
{
//jeeli ktos probuje sie dostac do stefy admin, zmien layout o takiej samej nazwie jak Routing.admin (core.php)
if (isset($this->params[Configure::read('Routing.admin')])) {
$this->layout = Configure::read('Routing.admin');
}
if (($this->layout == 'ajax') || ($this->layout == 'xls')) {
Configure::write('debug', 0);
}
}
function restrictAccess($cake = 0)
{
// sprawdzamy czy w sesji jest zmienna 'zalogowany' (zmienna tablicowa,swiadczy ze user jest zalogowany) i czy przekazany parametr
// znajduje sie w zmiennej tablicowaj 'zalogowany'
if (($this->Session->check("zalogowany")) && ($this->Session->read("zalogowany.Group.cake")>=$cake)) {
return true;
} else {
// jezeli nie jestesmy zalogowani to...
// wyciagnij wszystkie grupy z tabeli 'groups'
$groupsArray = $this->Group->find('all', array( 'fields' => 'Group.id', 'order' => 'id ASC', 'recursive' => 0));
// tworzymy tabele pomocnicza
$groups = array();
foreach( $groupsArray as $thisGroups) {
$groups[] = $thisGroups['Group']['id'];
}
// wytnij kawalek tablicy , opis funkcji pobierzIdGrupy(), sprawdzDostepPoIdGrupy() ponizej....reszte przeanalizujcie sami
$groups = array_slice( $groups, 0, ($this->pobierzIdGrupy()-1));
$this->sprawdzDostepPoIdGrupy( $groups );
$this->Session->write("adresProbyWejscia",str_replace('url=','',$_SERVER['QUERY_STRING']));
$this->Session->setFlash("Proszę się zalogować");
$this->redirect($this->loginForm);
}
}
// ta funkcja sprawdza nam czy dany user ma dostep do danej czesci witryny w zaleznosci od jego group_id, funkcja bedzie wykorzystywana
// wszedzie tam , gdzie chcemy zastrzec sobie dostep tylko dla danych userow z danej grupy...ponizej pokaze jak to zrobic...
function sprawdzDostepPoIdGrupy($groups = null)
{
if (!empty($groups)) {
if (is_array($groups) && in_array($this->Session->read("zalogowany.Group.id"),$groups)) {
return true;
} elseif (!is_array($groups) && $this->Session->read("zalogowany.Group.id")==$groups) {
return true;
} else {
$this->Session->write("adresProbyWejscia",str_replace('url=','',$_SERVER['QUERY_STRING']));
$this->Session->setFlash("Nie masz dostępu do tej części witryny");
$this->redirect($this->loginForm);
}
}
}
// funkcja wyciaga z sesji group_id danego usera
function pobierzIdGrupy()
{
if ($this->Session->check("zalogowany")) {
return $this->Session->read("zalogowany.Group.id");
} else {
return false;
}
}
to tyle jezeli chodzi o app_controllera, teraz czas na users_controller.php, a konkretnie funkcje ‘login’
// users_controller.php
function login()
{
// po wypelnieniu formularza logowania
if (empty($this->data))
{ // pokaz formularz logowania
}
else
{ // proba zalogowania
$this->data['User']['passwd'] = md5($this->data['User']['passwd']);
$this->User->recursive = 1;
// sprawdzamy czy istnieje taki user oraz czy jego konto jest aktywne, czyli active = 1
$user = $this->User->find("User.email='".$this->data['User']['email']."' AND passwd='".$this->data['User']['passwd']."' AND User.active = 1");
if (!empty($user))
{
// jezeli istnieje taki user zaladuj do jego sesji jego dane
$this->Session->write("zalogowany",$user);
// jezeli user probuje dostac sie do zastrzezonej czesci serwisu i nie ma pozwolenia...porzekieruj do strony logowania.
// w innym przypadku kontynuuj
if ($this->Session->read("adresProbyWejscia")<>'')
{
$strzezonaAkcja = (bool)(strpos($this->Session->read("adresProbyWejscia"), Configure::read('Routing.admin'), 0) === 0);
if ($strzezonaAkcja && $user['Group']['cake']=='0')
{
$this->Session->setFlash("Przepraszamy ".$user['User']['userName'].", ale nie możesz dostać się do panelu administracyjnego.");
$this->redirect($user['Group']['adresProbyWejscia']);
exit();
}
else
{
if($this->Session->read("adresProbyWejscia") == Configure::read('Routing.admin')) {
$this->redirect($user['Group']['przekierujPoZalogowaniu ']);
} else {
$this->redirect($this->Session->read("przekierujPoZalogowaniu "));
}
}
}
else
{
$this->redirect($user['Group']['przekierujPoZalogowaniu ']);
}
exit();
}
else
{
$this->Session->setFlash("Zły email (login) lub hasło.");
$this->redirect($this->loginForm);
}
}
}
i teraz cala magia : jezeli ktos bedzie chcial sie dostac do czesci serwisu zawierajacego ‘Routing.admin’. np. funckji ‘admin_add’ kontrolera ‘news’, wowczas to logowanie sprawdzi czy dany user jest zalogowany oraz czy ma tam dostep.
Natomiast jezeli bedziemy chcieli ograniczyc dostep do jakiejs funckji np. ‘add’ kontrolera ‘news’ robimy to tak
function add()
{
// wywolaj funkcje z app_controllera z parametrami w postaci tablicy, gdzie chcemy aby do tej funkcji mieli tylko Super Admini oraz Admin,
// Klienci nie beda posiadali dostepu
$this->sprawdzDostepPoIdGrupy(array(1,2))
}
Aha, jeszcze jedna sprawa, formularz logowani (views/users/login.ctp)
<form action="/users/login/" method="post" id="loginForm">
<?php echo $form->input('User.email');?>
<?php echo $form->input('User.passwd');?>
<?php echo $form->submit();?>
</form>
Mam nadzieje ze ten system przyda sie komus. Sadze ze jest dosc prosty w przeanalizowaniu. Napewno skuteczny..przynajmniej tak mi sie wydaje. Powodzenia w uzytkowaniu.