Cuma, 28 Kasım 2008

CodeIgniter'da Kullanıcıları Yetkilendirme

 

CodeIgniter'da bir çok değişik yetkilendirme (authorization) sınıfı kullanılsa da, ben basit ve kullanımı kolay olması nedeniyle Michael Wales'ın hazırladığı ErkanaAuth isimli kütüphaneyi kullanıyorum.

Michael Wales'ın sitesinin kullanım dışı olması nedeniyle kodu buraya da ekledim:

<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
 * ErkanaAuth by Michael Wales
 */

class Auth {
    var $CI;
/*   for PHP 5*/
    function __construct() {
        $this->CI =& get_instance();
        log_message('debug', 'Authorization class initialized.');
        
        $this->CI->load->database();
    }
       function try_login($condition = array()) {
        $this->CI->db->select('id');
        $query = $this->CI->db->getwhere('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;
        }
    }
    
    
     function logout() {
        $this->CI->session->set_userdata(array('user_id'=>FALSE));
  $this->CI->session->set_userdata(array('unit'=>FALSE));
  $this->CI->session->set_userdata(array('pr_id'=>FALSE));
    }
 }

Bu kodu application/libraries dizini altına auth.php olarak kayıt ediyorsunuz. Kullanımı için application/config dizini altında autoload.php dosayını açarak :

$autoload['libraries'] = array('database', 'session', 'auth');

kütüphanelerini açılışta yüklenmesi için otomatik ekliyorsunuz. MySQL veritabanında ci_cookies tablosunu aşağıdaki gibi yaratmış olmanız ayrıca gerekir:

CREATE TABLE IF NOT EXISTS `ci_sessions` (
  `session_id` varchar(40) NOT NULL default '0',
  `ip_address` varchar(16) NOT NULL default '0',
  `user_agent` varchar(50) NOT NULL,
  `last_activity` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`session_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Kütüphanenin kullanımı ise basitçe şöyle: kendinize ait bir tane MY_Controller.php dosyasını application/libraries dizini altına yaratıyorsunuz. Bu dosyanızda Registered user ve Authorized user diye iki farklı user tanımlıyorsunuz.

<?php if (!defined('BASEPATH')) exit('No direct access allowed.');
/*****
  * This class provides a set of base Controller classes to be utilized with ErkanaAuth
  * @author     Michael Wales
  * @email      webmaster@michaelwales.com
  * @filename   MY_Controller.php
  * @title      ErkanaAuth Controller Library
  * @url        http://www.michaelwales.com/
  * @version    1.0
  *****/

// Controllers accessible by everyone, regardless of login status
class Public_Controller extends Controller {
    function Public_Controller() {
        parent::Controller();
        // Get the user data, in case they are logged in
        $this->data->user = $this->auth->get_user($this->session->userdata('user_id'));
    }
    
    // This function is used to prevent a user from accessing a method if they are logged in
    function no_user_access() {
        if ($this->data->user !== FALSE) {
            redirect('error/user');
        }
    }
 
}

// Controllers only accessible by logged in users
class Auth_Controller extends Public_Controller {
    function Auth_Controller() {
        parent::Public_Controller();
        if ($this->data->user === FALSE) {
            // The user is not logged in, send them to the homepage
            redirect('member/login');
        }
    }
}

Ayrıca isteğinize ya da kullanım amacınıza göre daha fazla user tipi de burada tanımlayabilirsiniz. Bu dosyada yazdığınız Public_User, giriş için herhangi bir doğrulama istemeyen bölümlere, Auth_User ise girişinde şifre ve kullanıcı adı ile doğrulama isteyen bölümlere kullanılacaktır.

Şöyle ki: şifre istemeyen bir bölüme ait controller aşağıdaki gibi başlarken:

class Main extends Public_Controller {

 function Main()
 {
  parent::Public_Controller();
 }

Şifre ve kullanıcı adı doğrulaması isteyen bölümlere ait bir controller başlangıcı şöyle olacaktır:


class Post extends Auth_Controller {

 function Post()
 {
  parent::Auth_Controller();
  $this->load->library('validation');
 }

Controller'ları böylece ayırdıktan sonra kod içinde tekrar bir sorgulama yapmaya gerek yoktur.

Yorumlar

Eğer application/config/config.php dosyasındaki şu satırı değiştirmediyseniz, MY_Controller.php dosyanızı çağırmanıza gerek yoktur:

$config['subclass_prefix'] = 'MY_';

Bu satırda, kendi yazdığınız altsınıfların adının nasıl başlayacağını söylemektesiniz. (MY_Controller, MY_Model vs. gibi)

CI =& get_instance(); bu satirda hata aliyorum ...

@Kerim Candemir: Bu kodlar PHP 5 versiyonuna göre yazılmıştır. PHP 4 kullanıyorsan, _construct methodu yerine aşağıda verdiğim fonksiyonu kullanmalısın:

    function Auth() {
        $this->CI =& get_instance();
        log_message('debug', 'Authorization class initialized.');
		$this->CI->load->database();
    }

    function logged_in() {
        // Checks if the user is logged in.
        if ($this->CI->session->userdata('user_id')) {
            return TRUE;
        } else {
            return FALSE;
        }
    }   

Kerim Bey'in bahsettiği hata php 5'te de alınıyor çünkü kodlarda 11. satırda

CI =& get_instance(); 

yazmışsınız. Serinin 3. örneğinde sunduğunuz uygulamada o satır

$this->
CI =& get_instance();

şeklinde verilmiş doğrusu bu olacak sanırım :)

Teşekkürler Muhittin. Düzelttim yazıda bulduğun hatayı.

Yanlız şöyle bir hata alıyorum.
Fatal error: Call to undefined method Auth::get_user() in C:\wamp\www\Devam eden calismalar\CodeIgniter\ana-dosyalar\libraries\My_Controller.php on line 17

@Serkan: Aynı makalenin kodlarının bir arada olduğu burada anlattığım yazıyı dene lütfen. Bu örnek fazla karışmasın diye get_user() fonksiyonunu eklemedim.

Yorum Ekle