Anda di halaman 1dari 13

Belajar konsep OOP dengan bahasa pemrograman PHP Lesson I

Diposting oleh Ivo Idham Perdameian pada 28 September 2011Tinggalkan komentar (1)Menuju ke komentar

Banyak sekali artikel dan tutorial yang membahas pembelajaran konsep OOP, namun hal itu masih terasa tidak memenuhi atau boleh dikatakan artikel dan tutorialnya tidak memuaskan. Nah dalam tutorial saya kali ini saya ingin membahas hal tersebut secara sederhana yang mudah dipahami untuk pemula dalam belajar konsep OOP dengan bahasa pemrograman PHP dan tutorial ini merupakan tutorial yang berkelanjutan dan saya akan bahas secara tuntas, jadi tunggu aja kelanjutan tutorial berikutnya karena tulisan ini hanya sekedar pengantar dari pembahasan yang panjang , setelah tutorial ini kita akan membuat source

code sebagai bentuk implementasi dari pembahasan dari artikel/tutorial yang dibahas, so stay upto date via rss juga boleh. Pengertian singkat OOP
OOP (Object Oriented Programming) adalah sebuah konsep pemograman yang berbasis objek, OOPmerupakan terobosan baru dalam pemrograman setelah pemrograman prosedural, pemrograman modular dan pemrograman abstraksi data.

Kenapa harus OOP?


OOP memberikan kemudahan bagi programmer dalam pembuatan sebuah program, memberikan fleksibilitas yang lebih,
kemudahan penggunaan program, dan dipakai luas dalam teknik piranti lunak skala besar. Selain itu dengan pemograman OOP kode yang dibuat akan lebih mudah dikembangkan dan dirawat dalam arti seorang programer bisa menambah sebuah objek baru tanpa harus menggangu dan merubah modul yang lain. Berikut ini keuntungan dari penggunaan OOP dalam pemograman : 1. 2. 3.

Reusability (kemampuan untuk digunakan kembali). Kode yang dibuat dapat digunakan kembali di aplikasi atau program
lainnya.

Extensibility (Kemampuan untuk dapat dikembangkan). Kita dapat membuat method yang baru atau mengubah yang
sudah ada sesuai dengan yang kita inginkan tanpa harus membuat kode dari awal.

Maintainability (Kemampuan untuk mudah dikelola), kode yang sudah dibuat lebih mudah untuk di maintain/manage.
Apabila aplikasi yang dibuat adalah aplikasi dengan skala besar dan apabila terjadi error atau kesalahan maka dengan OOP hal tersebut mudah ditangani karena pemograman yang menggunakan OOP sudah modularitas(memecahkan program yang besar menjadi bagian-bagian kecil) sehingga perbaikan cukup pada modulmodul tertentu saja tanpa harus mengubah modul yang lainnya.

Empat konsep utama OOP


Dalam pemograman OOP, ada empat hal yang harus diperhatikan karena hal tersebut merupakan konsep vital dari OOP tersebut. Berikut ini konsep tiga konsep utama tersebut: 1. 2. 3. 4.

Encapsulation/pembungkusan, merupakan penyembunyian informasi melalui private danprotected. Inheritance/pewarisan, adalah kemampuan untuk membuat class turunan yang mewarisi propertydan method dari kelas
induk.

Abtraction/abtraksi, adalah sebuah konsep yang merupakan representasi abstrak dari konsep dalam pemograman,
misalnya objek mobil merupakan representasi abstrak dari mobil dalam dunia nyata.

Polymorphism/banyak bentuk, seorang programer bisa memakai method dengan nama yang sama pada class-class yang
berbeda.

Untuk sementara cukup sampai di sini dulu, lain waktu saya akan menulis kelanjutannya.

[share] Membuat central authentication server di PHP

Kemarin ada yang PM ane, tanya gimana cara bedain aplikasi internal sama external. Karena itu sekalian ane bahas aja disini, gimana cara pisahin beberapa aplikasi, dan sekaligus melakukan single logon untuk mereka.

Untuk keperluan ini, yang ane pakai adalah: 1. webserver: Nginx, tetapi apache juga bisa 2. PHP 5.3 3. libssl untuk openssl 4. mysql 5. libcurl Ini adalah contoh config file nginx yang digunakan pada CAS server:
Code:

http { server { listen 80; root /srv/cas/public; index index.php index.html index.htm; server_name localhost; location / { try_files $uri $uri/ /index.html /index.php; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; } }

server { listen 8000; root /srv/cas/internal; location / { try_files $uri $uri/ /index.html; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; } } } Jadi pada nginx, dia akan listen pada port 80 dan 8000. Kemudian kita bisa membuat firewall untuk memblokir port 8000 agar tidak bisa diakses dari internet, jadi hanya aplikasi yang bisa menggunakan port 8000 untuk internal. Dengan config diatas, apabila nginx diakses melalui http://ipaddress/ maka dia akan serve file dari /srv/cas/public. Dan apabila diakses melalui http://ipaddress:8000/ maka dia akan serve file dari /srv/cas/internal. Sekarang, database... Untuk contoh, ane pake database yang cukup simple saja.. dibutuhkan minimal 3 tabel untuk ini. Informasi yang ane contohkan juga hanya nama user. Tabel application
Code:

id: varchar(50) key: text key adalah untuk menampung public key dari aplikasi agan. Tabel tickets
Code:

id: char(15) -> untuk menampung id tiket uid: varchar(50) -> asosiasi tiket dan user Mungkin bisa ditambahkan expired date? Jadi ticket yang kelamaan ga diakses akan dihapus dengan sendirinya. Bisa gunakan cron dengan mysql cleanup.sql untuk membersihkan tiket tiket ini. Tabel users
Code:

uid: varchar(50) name: varchar(200) pwd: char(200) Sesuaikan panjang pwd dengan password yang akan agan encrypt. Modul encryption bisa agan buat sendiri dengan implement ICasEncryption interface. Kemudian kita akan membuat modul untuk melakukan CAS authentication. Pertama adalah config modul yang dibutuhkan. Jelas, kita membutuhkan sebuah server, dan database untuk authentication.
PHP Code:

class ConnectionConfig { private $host; private $user; private $pass; private $schema;

function __construct($host, $user, $pass, $schema) { $this->host = $host; $this->user = $user; $this->pass = $pass; $this->schema = $schema; } public function getHost() {return $this->host;} public function setHost($host) {$this->host = $host;} public function getUser() {return $this->user;} public function setUser($user) {$this->user = $user;} public function getPass() {return $this->pass;} public function setPass($pass) {$this->pass = $pass;} public function getSchema() {return $this->schema;} public function setSchema($schema) {$this->schema = $schema;} }
PHP Code:

class ConfigObject { private $connection; private $apps; private $tickets; private $user; function __construct() { $this->apps = 'applications'; $this->tickets = 'tickets'; $this->user = 'users'; $this>connection = new ConnectionConfig('localhost', 'root', '', 'cas'); } public function getConnection() {return $this->connection;} public function setConnection($host, $user, $pass, $schema) { $cn = new ConnectionConfig($host, $user, $pass, $schema); $this->connection = $cn; } public function getApps() {return $this->apps;} public function setApps($apps) {$this->apps = $apps;} public function getTickets() {return $this->tickets;} public function setTickets($tickets) {$this->tickets = $tickets;} public function getUser() {return $this->user;} public function setUser($user) {$this->user = $user;} } Ini untuk config di CAS server nantinya. Cukup mudah dimengerti kan? masih simple sekali class-nya. Sekarang, kita perlu sebuah file encryption yang harus dibuat untuk melakukan authentication.
PHP Code:

interface ICasEncryption { public function getSalt($text);

public function encrypt($text, $salt); public function createSalt(); } class CasEncryption implements ICasEncryption { public function getSalt($text) { return ""; } public function encrypt($text, $salt) { return md5($text); } public function createSalt() { return ""; } } Terserah agan mau encrypt seperti apa, tetapi harus implement ICasEncryption, karena itu yang akan digunakan oleh CasServer untuk compare password. Untuk contoh, ane buat encryption biasa, dengan md5, tanpa salt. Silahkan merubahnya supaya lebih sakti
Last edited by magico; 04-07-2011 at 01:59 AM..
QUOTE KaskusAd - Create an KasAD / Buat Iklan KasAD

04-07-2011, 01:04 AM

#2

magico
kaskus addict UserID: 50559 8 Join Date: Jul 2008 Posts: 3,979

Sekarang, kita akan masuk ke main module, yaitu CasServer


PHP Code:

class CasServer { private $config; private $connection; public function getConfig() {return $this->config;} public function setConfig($config) { if ($config instanceof ConfigObject) $this->config = $config; } public function __construct() { $this->config = new ConfigObject(); $this->connection = NULL; } private function connect() { if ($this->connection) {return true;} $connect = $this->config->getConnection(); $this->connection = new mysqli($connect>getHost(), $connect->getUser(), $connect->getPass(), $connect>getSchema()); return true; } private function createTicket($uid) { $ticket = 'T'.uniqid(); $this->connect(); $config = $this->config;

$conn = $this->connection; $conn->real_query("INSERT INTO {$config>getTickets()} (id, uid) VALUES ('$ticket', '$uid')"); return $ticket; } public function createuser($uid, $name, $pass, $encryption) { $this->connect(); $conn = $this->connection; //sanitize $uid = $conn->real_escape_string($uid); $pass = $conn->real_escape_string($pass); $config = $this->config; if (!$encryption instanceof ICasEncryption) { trigger_error("ERROR: Need ICasEncryption object"); } //Periksa userid $result = $conn->query("SELECT count(uid) FROM {$config>getUser()} WHERE uid = '$uid'"); $row = $result->fetch_array(); if ($row[0] == 0) { //Tidak ada duplikat //Encrypt password $salt = $encryption->createSalt(); $enc = $encryption->encrypt($pass, $salt); //insert $conn->real_query("INSERT INTO {$config>getUser()} (uid, name, pwd) VALUES ('$uid', '$name', '$enc')"); return true; } else { return false; } } public function authenticate($uid, $pass, $encryption) { $this->connect(); $conn = $this->connection; //Sanitize $uid = $conn->real_escape_string($uid); $pass = $conn->real_escape_string($pass); $config = $this->config; if (!$encryption instanceof ICasEncryption) { trigger_error("ERROR: Need ICasEncryption object"); } //Ambil encrypted password $result= $conn->query("SELECT pwd FROM {$config>getUser()} WHERE uid = '$uid';"); $row = $result->fetch_array(); if ($row) { //User ditemukan, lakukan one way encryption

$text = $row[0]; $salt = $encryption->getSalt($text); $pass2 = $encryption->encrypt($pass, $salt); if ($text == $pass2) { //Hash sama, buat tiket $ticket = $this->createTicket($uid); return $ticket; } else { return false; } } else { return false; } } public function register($app, $key) { $this->connect(); $conn = $this->connection; //Sanitize $app=$conn->real_escape_string($app); $key=$conn->real_escape_string($key); $config = $this->config; //Check apakah sudah terdaftar $result = $conn->query("SELECT count(id) FROM {$config>getApps()} WHERE id = '$app'"); $row = $result->fetch_array(); if ($row[0] > 0) return false; //Register aplikasi baru $conn->real_query("INSERT INTO {$config>getApps()} (id, `key`) VALUES ('$app', '$key')"); return true; } public function redeem($app, $ticket) { $this->connect(); $conn = $this->connection; //Sanitize $app = $conn->real_escape_string($app); $ticket = $conn->real_escape_string($ticket); $uid = ''; $key = ''; $user['uid']=''; $user['name']=''; $config = $this->config; //Ambil data user sesuai tiket $query = "SELECT `key` FROM {$config>getApps()} WHERE id = '$app'; SELECT u.uid, u.name FROM {$config->getTickets()} t INNER JOIN {$config>getUser()} u ON u.uid = t.uid

WHERE id = '$ticket'"; if ($conn->multi_query($query)) { $data = $conn->store_result(); $row = $data->fetch_array(); $key = $row[0]; if ($conn->next_result()) { $data = $conn->store_result(); $row = $data->fetch_array(); $user['uid']= $row[0]; $user['name']= $row[1]; } else { //Tiket tidak ditemukan return false; } } else { echo $conn->error; } //Encrypt sesuai public key $data = json_encode($user); $crypted = ''; openssl_public_encrypt($data, $crypted, $key); return base64_encode($crypted); } } Pertama, method setConfig, akan memastikan agan bisa mengatur config dari CasServer ini sesuai object ConfigObject diatas. setApps() akan mengatur nama tabel untuk aplikasi, setUser() untuk tabel user, dan setTickets() untuk tabel penampung tiket. Kemudian default connection bisa diatus melalui setConnection pada ConfigObject. Setelah agan mengatur ConfigObject, agan bisa mengirimkannya melalui setConfig(). Misalnya:
PHP Code:

$config = new ConfigObject(); $config>setConnection('localhost', 'useragan', 'rahasiadong', 'schemaane' ); $config->setApps('aplikasineh'); $cas = new CasServer(); $cas->setConfig($config); Kemudian ada method createuser dan authenticate yang akan mengatur user. Keduanya menerima $encrytion parameter sebagai object yang akan melakukan encrypt terhadap password tersebut. Keduanya meminta ICasEncryption interface. Jadi misalnya agan membuat Encryption berikut:
PHP Code:

class IniEncryption implements ICasEncryption { public function getSalt($text) { .... } public function encrypt($text, $salt) { .... } public function createsalt() { .... } }

Maka agan akan bisa pass sebagai cara enkripsi password seperti ini:
PHP Code:

$cas>createuser('magic', 'Ane nehh', '123456', new IniEncryption()); Maka password 123456 akan diencrypt sesuai code agan pada class IniEncryption getSalt adalah untuk extract Salt dari text yang sudah disimpan, dan createSalt adalah Salt generator. Sedangkan encrypt adalah untuk melakukan encryption dan hashing. Jadi pastikan kalau membuat encryption dengan salt, pastikan agan bisa mengambil salt-nya. Setelah pemeriksaan selesai, maka modul authenticate akan membuat tiket dengan memanggil createticket(), dan menyimpannya ke database. Method register adalah untuk registrasi aplikasi. Aplikasi yang register harus mengirimkan public key-nya, dan application id. key ini nantinya akan digunakan untuk encrypt data yang dikirimkan ke luar. Jadi biarpun agan tahu bahwa aplikasi menggunakan nama 'testapp', dengan nomor tiket '12345', tetapi agan tidak akan bisa membaca datanya apabila agan tidak memiliki private key untuk membuka kuncinya. Kita sampai pada bagian terakhir, yaitu CasClient
PHP Code:

class CasClient { private $keypath = '/srv/test/private.key'; private $appname; private function savekey($key) { file_put_contents($this->keypath, $key); } private function loadkey() { $key = file_get_contents($this->keypath); return $key; } public function __construct($appname) { $this->appname = $appname; } public function register($url) { //Generate SSL encryption key $key=openssl_pkey_new(); openssl_pkey_export($key, $privatekey); $public_key = openssl_pkey_get_details($key); $public_key = $public_key['key']; $app = $this->appname; //Save key ke config file $this->savekey($privatekey); //Register ke url yang diberikan $ch = curl_init($url); $param = 'id='.$app.'&key='.urlencode($public_key); curl_setopt($ch, CURLOPT_POST, 2); curl_setopt($ch, CURLOPT_POSTFIELDS, $param); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); curl_close($ch); return $result == "OK";

} public function redeem($url, $ticket) { $key = $this->loadkey(); $app = $this->appname; //Request data ke url yang diberikan $ch = curl_init($url); $param = 'id='.$app.'&ticket='.urlencode($ticket); curl_setopt($ch, CURLOPT_POST, 2); curl_setopt($ch, CURLOPT_POSTFIELDS, $param); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); $result= base64_decode($result); curl_close($ch); //decrypt data $decrypted=""; openssl_private_decrypt($result, $decrypted, $key); return $decrypted; } } Modul ini digunakan pada aplikasi client yang akan melakukan otentikasi ke CAS server. Pada waktu register, client akan membuat sebuah RSA key, dan mengirimkan public key-nya ke server supaya server bisa melakukan encrypt, dan menyimpan private key-nya pada folder tertentu. Agan bisa rubah folder tersebut, tetapi pastikan agan bisa menulis ke sana. Tanpa private key ini, data yang dikirim oleh CasServer tidak akan bisa dibaca oleh method redeem(). $appname disini adalah identifikasi aplikasi, yang akan disimpan oleh server CasServer dan digunakan untuk melakukan enkripsi.
Last edited by magico; 04-07-2011 at 01:32 AM..
QUOTE 04-07-2011, 01:40 AM

#3

magico
kaskus addict UserID: 5055 98 Join Date: Jul 2008 Posts: 3,979

Kelemahan dari modul yang ane buat ini, adalah siapapun bisa melakukan registrasi, apabila bisa mengakses ke page dengan registrasi ini. Karena itu ane membuatnya pada port internal, supaya user tidak bisa mengakses port ini. Ada cara lain, yaitu membatasi data aplikasi dan melakukan verifikasi sebelum data boleh digunakan oleh method redeem() pada CasServer Berikutnya, life example dari modul modul ini Pada folder /srv/cas/internal registrasi.php
PHP Code:

require_once 'init.inc'; if (!isset($_POST['id'])) { die(); } $app = $_POST['id']; $key = $_POST['key']; $cas=new CasServer();

$result = $cas->register($app, $key); if ($result) echo "OK"; else echo "FAIL"; redeem.php
PHP Code:

require 'init.inc'; if (!isset($_REQUEST['id'])) { die(); } $app = $_REQUEST['id']; $ticket = $_REQUEST['ticket']; $cas = new CasServer(); $data = $cas->redeem($app, $ticket); if ($data) echo $data; Pada folder /srv/cas/public login.php
PHP Code:

<?php require_once 'init.inc'; $error_string = ''; if (isset($_REQUEST['ref'])) { $ref = $_REQUEST['ref']; } else { die(); } if (isset($_POST['user']) && isset($_POST['pass'])) { $cas = new CasServer(); $uid = $_POST['user']; $pass = $_POST['pass']; $config = new ConfigObject(); $config->setConnection('localhost', 'root', '', 'sso'); $cas->setConfig($config); $ticket = $cas>authenticate($uid, $pass, new CasEncryption()); if ($ticket) { header("location: $ref?ticket=$ticket"); die(); } else { $error_string = "Maaf, tidak dapat menemukan data anda< br/>"; } } ?> <h2>Contoh login gateway untuk CAS Server</h2> <br/> Anda masuk kesini karena akan masuk dari:<br/> <? echo $ref ?><br/> <br/> Silahkan login:<br/> <? echo $error_string; ?>

<form method="post" action="/login/login.php"> <input type="hidden" name="ref" value="<? echo $ref; ?>" /> User: <input type="textbox" name ="user" /><br/> Pass: <input type="password" name ="pass" /><br/> <input type ="submit" value ="Login"/> </form> Hanya itu saja pada publik.

Kemudian pada server client, entah di mana Untuk melakukan registrasi:


PHP Code:

require_once('init.inc'); $url = 'http://localhost:8000/register.php'; $app = 'testapp'; $cas = new CasClient($app); $status = $cas->register($url, $app); if ($status) echo "OK"; else echo "fail"; dan ini adalah untuk login
PHP Code:

<?php require_once 'init.inc'; $loginpage = '/login/login.php'; if (!isset($_GET['ticket'])) { header('location: '.$loginpage.'?ref='.$_SERVER['PHP_SELF'] ); die(); } $ticket = $_GET['ticket']; $url $app $cas $uid ?> Jadi total ada 3 project disini.. Pertama untuk port internal, kemudian port external, dan client application. Tiket bisa agan simpan pada AJAX, sehingga bisa dilakukan pengiriman ke beberapa aplikasi yang terdaftar pada CAS. Semoga bisa bermanfaat untuk agan. EDIT: Oh, ane lupa.. registration ke CAS hanya cukup satu kali seumur hidup program. Jadi ga perlu tiap mau redeem harus register. = = = = 'http://localhost:8000/redeem.php'; 'testapp'; new CasClient('testapp'); $cas->redeem($url, $ticket);

echo $uid;