Mengintegrasikan Two-Factor otentikasi dengan CodeIgniter
() translation by (you can also view the original English article)
Dengan string hari profil tinggi pembobolan (hacks) di Sony dan perusahaan lain, ini adalah waktu yang Anda mengambil melihat kedua keamanan situs web Anda. Two-factor otentikasi adalah sebuah langkah dalam arah yang benar untuk mengamankan situs web Anda dari attacker. Dalam tutorial ini, kita akan implementasinya ini dalam aplikasi CodeIgniter kami.
Apa yang dimaksud dengan Two-Factor otentikasi?
Two-factor otentikasi mengharuskan user untuk menggunakan sesuatu yang mereka tahu, seperti username dan password, dan sesuatu yang mereka miliki, seperti telepon, untuk masuk.
Akhir-akhir ini, perusahaan-perusahaan seperti Google dan Facebook telah menggunakan two-factor otentikasi pengguna mereka. Layanan lain, seperti MailChimp, menggunakan form alternatif two-factor otentikasi untuk membantu menggagalkan penyerang. Tapi tetap, apa bagusnya two-factor otentikasi?
Two-factor otentikasi adalah cara untuk membuktikan identitas Anda berdasarkan nama pengguna dan sandi, serta perangkat fisik yang Anda bisa bawa dengan Anda.



Aplikasi mobile Duo mendukung push notification untuk otentikasi!
Hal ini membuat jauh lebih sulit bagi penjahat untuk mencuri identitas Anda, karena mereka akan perlu akses ke telepon atau perangkat keras token - bukan hanya identitasnya login Anda.
Beruntung bagi Anda, Duo Security menawarkan layanan two-facto gratis ideal bagi siapa pun yang mencari untuk melindungi situs web mereka.
Tidak hanya Duo gratis, tapi penuh fitur. Mereka membiarkan Anda mengotentikasi dalam berbagai cara, termasuk:
- Phonecall otentikasi
- Berbasis SMS Token
- Aplikasi mobile token generator
- Otentikasi Push-based
- Hardware token tersedia untuk pembelian
Langkah 1: Setup
Setup CodeIgniter
Jika Anda belum memakai CodeIgniter sebelumnya, saya sangat menyarankan Anda memeriksa CodeIgniter dari awal seri pertama.
Tutorial ini akan membangun otentikasi mudah dengan CodeIgniter tutorial. Tutorial ini akan jauh lebih mudah bagi Anda untuk memahami jika Anda menyelesaikan tutorial sebelumnya sebelum melanjutkan. Kita akan menggunakan file dari tutorial yang sebagai titik awal kita.
Pastikan bahwa config/autoload.php
Anda memiliki helper berikut yang dimuat.
1 |
$autoload['helper'] = array('url', 'form'); |
Buat akun
Silahkan ke Duo Security, dan mendaftar untuk account.
Mereka menawarkan free plan untuk proyek sumber terbuka, dan untuk situs dengan kurang dari 10 user Duo (Duo user adalah seseorang yang akan menggunakan dua faktor otentikasi untuk log in).
Membuat integrasi
Setelah mendaftar, Anda perlu untuk login ke Duo dan membuat integrasi. Setelah log in, klik pada integrations pada panel sisi menarik halaman integrasi. Dari sana, klik tombol "New Integration".
Pastikan Anda membuat integrasi adalah integrasi Web SDK. Ini akan memungkinkan Anda untuk menggunakan PHP API dengan CodeIgniter.



Nama integrasi hanya digunakan pada Duo website. Ini adalah hanya satu cara bagi Anda untuk mengidentifikasi integrasi. Duo ini memiliki panduan memulai yang menjelaskan cara mengatur integrasi.
Download Web SDK
Selain pengaturan integrasi, Anda akan perlu untuk men-download Web SDK.
Ada dua bagian SDK yang kita perlukan: file PHP (duo_web.php) dan JavaScript file. Harap dicatat bahwa JavaScript memiliki ketergantungan jQuery dan JavaScript paket datang dengan jQuery.
Kita akan menggunakan JavaScript paket, tetapi perhatikan bahwa jika Anda tidak, jQuery harus dimuat sebelum JavaScript disediakan oleh Duo. Untuk informasi lebih lanjut tentang Web SDK dan bagaimana cara kerjanya, lihat dokumentasi di http://www.duosecurity.com/docs/duoweb
Langkah 2: Modifikasi untuk keamanan
Setelah menyelesaikan otentikasi mudah dengan CodeIgniter tutorial, Anda harus memiliki sistem dasar login di tempat.
Hashing lebih baik
Sebagai langkah pertama, kami akan menambahkan fungsi hashing kuat ke database. Openwall memiliki nice hashing PHP perpustakaan yang mengimplementasikan bcrypt
. Versi terbaru dari phpass adalah 0.3 pada saat artikel ini.
Pergi ke depan dan download phpass dari situs web mereka: http://openwall.com/phpass/. Setelah men-download dan unarchiving folder, Anda akan perlu untuk menaruhnya dalam folder libraries.
Kita sekarang harus membuat sendiri Perpustakaan file sebagai antarmuka untuk phpass. Buat sebuah file Perpustakaan baru yang bernama password.php
. Perpustakaan kami akan memiliki dua fungsi:
- sebuah fungsi hash untuk menghash password lama
- fungsi check_password untuk membandingkan hash dengan password plaintext.
1 |
require_once('phpass-0.3/PasswordHash.php'); |
2 |
|
3 |
class Password { |
4 |
|
5 |
var $hasher; |
6 |
|
7 |
function __construct() |
8 |
{
|
9 |
// 8 is the hash strength. A larger value can be used for extra security.
|
10 |
// TRUE makes the passwords portable. FALSE is much more secure.
|
11 |
$this->hasher = new PasswordHash(8, TRUE); |
12 |
}
|
13 |
|
14 |
function hash($pass) |
15 |
{
|
16 |
return $this->hasher->HashPassword($pass); |
17 |
}
|
18 |
|
19 |
function check_password($pass, $hash){ |
20 |
return $this->hasher->CheckPassword($pass, $hash); |
21 |
}
|
22 |
}
|
Pernyataan require_once()
memastikan bahwa kami akan dapat menggunakan class PasswordHash
dari phpass.
PasswordHash
mengambil dua argumen dalam konstruktor yang:
- sejumlah menunjukkan kekuatan hash
- boolean mengenai apakah atau tidak password harus portabel.
Dalam kasus ini, kita akan membuat password kita portabel.
Ini pada dasarnya berarti bahwa hash tidak kuat, tapi jika kita pernah perlu beralih server atau memindahkan database, kita dapat membuat salinan. Jika kita tidak menggunakan skema hashing portabel, kami menjalankan risiko mengalami semua user kami membuat kata sandi baru jika database akan dipindahkan.
Catatan: Meskipun kami sedang mengimplementasikan hashing fungsi yang kuat, Anda masih harus memerlukan user untuk memiliki password yang kuat.
Mengubah Admin Model
1 |
public function verify_user($email, $password) |
2 |
{
|
3 |
$q = $this |
4 |
->db |
5 |
->where('email_address', $email) |
6 |
->limit(1) |
7 |
->get('users'); |
8 |
|
9 |
if ( $q->num_rows > 0 ) { |
10 |
$result = $q->row(); |
11 |
$this->load->library('password'); |
12 |
|
13 |
//Make sure the hashes match.
|
14 |
if($this->password->check_password($password, $result->password)){ |
15 |
return $result; |
16 |
}
|
17 |
}
|
18 |
return false; |
19 |
}
|
Sebelumnya, kami telah memilih iser dengan alamat email dan sandi yang dihash. Sekarang kami mendapatkan user dari database berdasarkan alamat email. Ini berarti kita memiliki untuk memvalidasi password sebelum kita dapat mengembalikannya ke pengguna.
Setelah kami telah mendapaktan user dari database, kita akan memuat Perpustakaan sandi yang kami hanya dibuat dan pastikan bahwa password yang dimasukkan sesuai sandi yang di hash.
Jika kedua password cocok, kita melanjutkan mengembalikan user, jika tidak, kita mengembalikan false
.
Pastikan untuk menggunakan perpustakaan sandi untuk hash password baru untuk diri sendiri. Password dalam database Anda akan menjadi tidak valid sekarang!
Mengubah tabel Users
Kita akan menambahkan sebuah field dasar pemission ke database. permission ini akan menentukan apakah atau tidak user akan log in dengan two-factor otentikasi.
Kita perlu menambahkan kolom tabel users untuk two-factor permission. Anda dapat melakukan ini melalui phpMyAdmin, atau menjalankan SQL berikut.
1 |
ALTER TABLE users ADD two_factor_permission BOOLEAN NOT NULL; |
Nilai 1 di kolom permission akan membuat menggunakan two-factor otentikasi pengguna.
SQL akan menambah kolom boolean tabel users. Kita akan menggunakan ini untuk mengharuskan pengguna untuk menggunakan two-factor otentikasi, atau untuk mem-bypass.
Jika Anda melakukan hak ini, Anda akan melihat kolom baru di tabel users. Anda akan perlu untuk memperbarui record saat ini, atau masukkan recotr baru yang menetapkan two_factor_permission
ke true
(1).
Jika kolom ini diatur ke false
(0), pengguna akan dapat untuk memotong otentikasi two-factor. Ini sangat ideal bagi pengguna yang tidak memerlukan tingkat yang sama keamanan sebagai administrator.
Langkah 3: Menggunakan Permission Setting
Kita akan membutuhkan cara untuk bypass otentikasi sekunder, serta cara untuk memasukkan langkah otentikasi sekunder untuk proses login.
Bypassing otentikasi sekunder
Pertama, kita akan perlu cara untuk bypass otentikasi sekunder. Ini berarti bahwa kita harus memeriksa user dalam admin controller.
1 |
if ( $res !== FALSE ) { |
2 |
$_SESSION['username'] = $res->email_address; |
3 |
if ( $res->two_factor_permission ) { |
4 |
$this->_second_auth($res->email_address); |
5 |
return; |
6 |
}
|
7 |
else { |
8 |
$_SESSION['logged_in'] = TRUE; |
9 |
redirect('welcome'); |
10 |
}
|
11 |
}
|
Ini akan memeriksa untuk melihat jika pengguna harus log in dengan dua faktor sistem kami.
Jika pengguna harus menggunakan otentikasi two-factor, kami ingin mereka untuk pergi ke halaman otentikasi sekunder tanpa me-login kan mereka.
Daripada mengarahkan user, kami dapat memanggil fungsi _second_auth()
dan memiliki yang memuat halaman. statement "return
" menghindari loading login form.
Kami telah membuat logged_in
variabel session baru yang akan kita gunakan untuk memverifikasi bahwa pengguna telah dicatat. Ini berarti kita perlu membuat beberapa perubahan untuk redirect.
Memperbaiki Redirect
Ada dua redirect yang perlu diubah: yang pertama adalah dalam fungsi index admin controller.
1 |
if ( isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === TRUE ) { |
2 |
redirect('welcome'); |
3 |
}
|
Yang lainnya adalah di controller welcome
. Kita perlu memastikan bahwa pengguna tidak login sebelum redirecting.
1 |
if ( !isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== TRUE ) { |
2 |
redirect('admin'); |
3 |
}
|
Memasukkan sekunder otentikasi
Sekarang kita perlu untuk menangani otentikasi sekunder.
Dalam fungsi admin/index
, kita memanggil _second_auth()
, jadi mari kita menulis fungsi dasar.
1 |
public function _second_auth ($username) |
2 |
{
|
3 |
echo "Welcome $username, you are looking at a secondary authentication page."; |
4 |
}
|
Langkah 4: Membangun View
Sistem otentikasi tradisional memperlakukan login sebagai satu langkah proses.



Duo memberi kita sedikit JavaScript dan HTML untuk menyuntikkan antara dua langkah. Ini berarti kita harus membuat view dengan kode yang dibutuhkan.



Mari kita membuat view baru, disebut second_auth.php
dalam folder views
. Kita harus menyisipkan iframe dan JavaScript yang disediakan oleh Duo untuk membuatnya bekerja.
Anda harus membuat sebuah halaman dengan struktur HTML dasar. Berikut dapat ditempatkan dalam body:
1 |
<iframe id="duo_iframe" width="100%" height="500" frameborder="0"></iframe> |
2 |
<script type="text/javascript" src="/path/to/Duo-Web-v1.js" ></script> |
Dalam setup khas, Anda akan menyimpan semua JavaScript Anda dalam folder resource. Di sini, kami telah menempatkan folder resources
di root dari situs kami, dengan 'js
' sub folder yang berisi file Web SDK JavaScript.
src
kami akan terlihat seperti:
1 |
src="<? echo base_url(); ?>resources/js/Duo-Web-v1.js" |
Kita juga perlu menambahkan sedikit JavaScript.
1 |
<script type="text/javascript" > |
2 |
Duo.init({ |
3 |
'host':'<?php echo $host; ?>', |
4 |
'post_action':'<?php echo $post_action; ?>', |
5 |
'sig_request':'<?php echo $sig_request; ?>' |
6 |
}); |
7 |
</script> |
Kami akan menghasilkan data dari controller segera.
Memasukkan Form
Jika Anda mengikuti tutorial sebelumnya, Anda harus mengkonfigurasi CodeIgniter untuk melindungi terhadap CSRF.
Karena JavaScript akan mengirim data ke controller kami, CodeIgniter akan mencari CSRF token. Jika kita tidak memiliki token ini, kita akan mendapatkan kesalahan.
Kami menggunakan JavaScript akan menyerahkan form dengan id "duo_form
". Semua yang perlu kita lakukan adalah membuat itu.
1 |
echo form_open('admin', array('id'=> "duo_form")); |
2 |
echo form_close(); |
Dengan menggunakan form class, CodeIgniter secara otomatis akan menyuntikkan token. Ketika form akan diposting, CodeIgniter akan menemukan token dan mari kita lanjutkan.
Langkah 5: Mempersiapkan Data
Kembali di admin
controller, kita perlu untuk menghasilkan beberapa data dalam fungsi _second_auth()
kami.
Host adalah API URL yang Anda berikan dengan ketika Anda mendaftar dengan Duo. URL ini harus melihat sesuatu seperti api-xxxxxxxx.duosecurity.com
(di mana 'xxxxxxxx' adalah string yang unik yang terikat pada account Duo Anda).
1 |
$data['host'] = "api-xxxxxxxx.duosecurity.com"; |
Ingatlah untuk mengganti host dengan URL tertentu. URL di atas tidak akan bekerja.
action post adalah URL yang akan menangani respon setelah pengguna telah mencoba untuk melakukan otentikasi dengan Duo.
Kami akan membuat fungsi lain di controller admin untuk menangani post-back. Untuk sekarang, kita akan nama fungsi process_second_auth()
.
1 |
$data['post_action'] = base_URL() . "admin/process_second_auth"; |
Loading PHP Web SDK
Pastikan Anda mengubah nama 'duo_web.php' ke 'duo.php' untuk menghindari kesalahan CodeIgniter.
Jika Anda belum download salinan terbaru duo_web.php, Anda bisa mendapatkannya dari halaman Web SDK GitHub Duo.
Karena Web SDK datang sebagai class PHP, kita dapat mengubah nama itu ke "duo.php
" dan menempatkannya dalam folder "application/libraries" kami.
Setelah Anda telah menempatkan file ke folder libraries
, kita dapat memuat di controller kami.
1 |
public function _second_auth($username) |
2 |
{
|
3 |
$this->load->library('duo'); |
4 |
|
5 |
$data['host'] = "api-xxxxxxxx.duosecurity.com"; |
6 |
$data['post_action'] = base_URL() . "admin/process_second_auth"; |
7 |
|
8 |
echo "Welcome $username, you are looking at a secondary authentication page."; |
9 |
}
|
Menghasilkan Signed Request
Untuk memahami bagaimana untuk menghasilkan sig_request
, Anda harus memahami apa yang akan kita generate.
Variabel
$akey
perlu setidaknya 40 karakter, sebaliknya Perpustakaan Duo akan mengembalikan kesalahan!
Duo Web SDK menciptakan dua signed tokens, satu dengan secret token yang dikasih ke anda, satunya dengan kunci aplikasi yang Anda membuat.
adalah kombinasi dari dua Token.sig_request
Dengan membuat key aplikasi Anda sendiri, Anda akan memiliki lapisan kedua keamanan. Attacker akan memerlukan secret key dari Duo dan kunci pribadi untuk spoof token.
Sekarang kita akan menghasilkan 'sig_request'. Duo akan menyediakan Anda dengan integrasi key dan secret key bila Anda membuat integrasi.
Pastikan untuk mengganti di bawah teks dengan integrasi key dan secret key yang diberikan kepada Anda. Anda perlu untuk membuat secret key Anda sendiri. Itu harus setidaknya 40 karakter, dan harus sebagai acak mungkin.
1 |
public function _second_auth($username) |
2 |
{
|
3 |
$this->load->library('duo'); |
4 |
|
5 |
// Duo Integration Key
|
6 |
$ikey = "REPLACE WITH YOUR DUO INTEGRATION KEY"; |
7 |
|
8 |
// Duo Secret Key
|
9 |
$skey = "REPLACE WITH YOU DUO SECRET KEY"; |
10 |
|
11 |
// Personal Application Key
|
12 |
$akey = "CREATE AN APPLICATION KEY"; |
13 |
|
14 |
$data['host'] = "api-xxxxxxxx.duosecurity.com"; |
15 |
$data['post_action'] = base_URL() . "admin/process_second_auth"; |
16 |
$data['sig_request'] = $this->duo->signRequest($ikey, $skey, $akey, $username); |
17 |
|
18 |
echo "Welcome $username, you are looking at a secondary authentication page."; |
19 |
}
|
Duo signRequest()
akan menghasilkan token dan mengembalikan mereka sebagai string untuk pass ke sig_request
.
Sekarang kita perlu memuat data ke view yang kita buat sebelumnya.
1 |
public function _second_auth($username) |
2 |
{
|
3 |
$this->load->library('duo'); |
4 |
|
5 |
// Duo Integration Key
|
6 |
$ikey = "REPLACE WITH YOUR DUO INTEGRATION KEY"; |
7 |
|
8 |
// Duo Secret Key
|
9 |
$skey = "REPLACE WITH YOUR DUO SECRET KEY"; |
10 |
|
11 |
// Personal Application Key
|
12 |
$akey = "CREATE AN APPLICATION KEY"; |
13 |
|
14 |
$data['host'] = "api-xxxxxxxx.duosecurity.com"; |
15 |
$data['post_action'] = base_URL() . "admin/process_second_auth"; |
16 |
$data['sig_request'] = $this->duo->signRequest($ikey, $skey, $akey, $username); |
17 |
|
18 |
$this->load->view('second_auth', $data); |
19 |
}
|
Jika Anda mencoba untuk login sekarang, Anda akan melihat Halaman ini:

Ini adalah form pendaftaran. Anda dapat mendaftar ke ponsel Anda di sini, tapi kami tidak memiliki apa-apa untuk proses otentikasi sekunder sehingga itu tidak akan membuat kamu masuk.
Jika Anda tidak melihat apa-apa sama sekali, lihat sumber halaman untuk pesan error. error dengan data yang akan ditampilkan dalam<script>
tag
Jika ia mengatakan, "Access Denied", pastikan bahwa Anda telah memasukkan integrasi dan secret key dari Duo Security situs.
Langkah 6: Pengolahan sekunder otentikasi
Kami telah set post aksi kita menjadi admin/process_second_auth
, sehingga kita perlu membuat fungsi process_second_auth()
.
1 |
public function process_second_auth() |
2 |
{
|
3 |
if ( isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === TRUE ) { |
4 |
redirect('welcome'); |
5 |
}
|
6 |
}
|
Karena fungsi ini akan memiliki URL sendiri, kita perlu untuk mengarahkan user yang login.
Kita harus memuat Perpustakaan Duo lagi untuk memvalidasi data.
1 |
$this->load->library('duo'); |
2 |
|
3 |
// Same keys used in _second_auth()
|
4 |
$ikey = "REPLACE WITH YOUR DUO INTEGRATION KEY"; |
5 |
$skey = "REPLACE WITH YOUR DUO SECRET KEY"; |
6 |
$akey = "REPLACE WITH YOUR APPLICATION KEY"; |
Kami akan memerlukan $ikey, $ske
yang sama, dan $akey
dari _second_auth()
fungsi untuk memvalidasi data yang dikirim.
JavaScript posts mengembalikan sig_response
dari server Duo.
1 |
$sig_response = $this->input->post('sig_response'); |
2 |
$username = $this->duo->verifyResponse($ikey, $skey, $akey, $sig_response); |
Setelah kami telah mendapatkan sig_response
dari data yang dikirim, kami akan menjalankan melalui fungsi verifyResponse()
. Ini akan mengembalikan NULL jika Token tidak cocok, atau nama pengguna jika mereka berlaku.
1 |
if ( $username ) { |
2 |
$_SESSION['logged_in'] = TRUE; |
3 |
redirect('welcome'); |
4 |
}
|
5 |
else{ |
6 |
redirect('admin'); |
7 |
}
|
Akhirnya, kami akan memverifikasi bahwa username dikembalikan, dan menyelesaikan login mereka dengan menetapkan nilai $_SESSION ['logged_in']
ke true.
Semua bersama-sama fungsi akan terlihat seperti ini:
1 |
public function process_second_auth() |
2 |
{
|
3 |
if ( isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === TRUE ) { |
4 |
redirect('welcome'); |
5 |
}
|
6 |
|
7 |
$this->load->library('duo'); |
8 |
|
9 |
// Same keys used in _second_auth()
|
10 |
$ikey = "REPLACE WITH DUO'S INTEGRATION KEY"; |
11 |
$skey = "REPLACE WITH DUO'S SECRET KEY"; |
12 |
$akey = "REPLACE WITH YOUR APPLICATION KEY"; |
13 |
|
14 |
$sig_response = $this->input->post('sig_response'); |
15 |
$username = $this->duo->verifyResponse($ikey, $skey, $akey, $sig_response); |
16 |
|
17 |
if ( $username ) { |
18 |
$_SESSION['logged_in'] = TRUE; |
19 |
redirect('welcome'); |
20 |
}
|
21 |
else{ |
22 |
redirect('admin'); |
23 |
}
|
24 |
}
|
Sekarang Anda harus bisa login dengan two-factor otentikasi, silahkan mencobanya!
Kesimpulan
Mudah-mudahan Anda telah menyiapkan sistem otentikasi two-factor Anda sendiri untuk CodeIgniter!
Apa lagi yang bisa Anda lakukan? Ada banyak untuk melakukan dalam hal keamanan, tetapi peningkatan terbesar akan melacak tindakan user.
Sistem keamanan yang baik tidak hanya aman: ini akan membantu Anda mengidentifikasi mana kerentanan datang dari. Anda harus menjaga melacak yang login upaya, dan tindakan lain untuk memudahkan identifikasi attacker.
Terima kasih telah membaca! Jika Anda mengalami kesulitan, tinggalkan post di komentar.