PHP Two Factor Authentication Yapımı

PHP Two Factor Authentication Yapımı

Hepinize merhaba dostlarım 😊. Yine yopyoğun olan ve gözaçıp kapayıncaya kadar çok hızlı geçen bir haftanın (özellikle benim gözümden bakacak olursak 😅) ardından gelen soğuk bir pazar gününü güzel bir şekilde değerlendirmek istediğimiz artık çok net 😊. Bunu biz olarak yani ben adına söylemek istemiyorum çünkü bir aile gibi olduk sizinle. 

Bazı okuyucularımdan gelen (ciddi ciddi yaşadığım için diyorum) güzel yorumlar olsun, otobüste bazen bana gelip "Sen MFSoftware Blog sitesinin kurucusu musun" deyip bilgi alan yazılımcı dostlarımı görmek ve onlara yardımcı olmak beni inanılmaz mutlu ediyor. Dediğim gibi biz bir aile olduk 😊

Yine mutluluktan aşırı derece patlama yaşıyorum dostlarım bunu siz de anladınız ve zamanınızdan elimde olmadan çalmış oldum kusuruma bakmayın. Bu haftaki konumuza bakacak olursak hemen hemen her sistemde gördüğümüz "Two Factor Authentication" işlemini biz PHP programlama dili ile yapacağız. Amaaa konuya hızlıca girmeden önce bunun ufak bir açıklamasını yapalım derim 😊

Two Factor Authentication Nedir ?

Eveeeet dostlarım Bismillah diyelim konumuza girişimizi yapalım. Şimdi öncelikle arkanıza rahatça yaslanın ve beni dinleyin 😊. Bir sisteminiz olduğunu varsayalım dostlarım. Bu sisteminizde de kullanıcı hesapları olsun (sisteme üye olan kullanıcılar). Bu kullanıcılar sisteme login olacağında bunun bir bot hesap mı yoksa bunun bize bir saldırı niteliğinde olup olmadığı durumların önüne geçmek için Two Factor Authentication olayını kullanırız. Günümüzde çevremize baktığımızda Google, Facebook, Instagram gibi birçok büyük sistemlerde bunları rahatlıkla görebiliyoruz 😊

Şimdi kendimize şu soruyu soralım:

Dev firmalar bu altyapıyı sistemlerine dahil etmiş iyi güzel. Biz neden öğrenmiyoruz ki bunun mantığını ?

Bu söz size gelişimin kapılarını açacaktır dostlarım. Şu an gaza geldik farkındayım 😊. O halde hemen kodlamaya geçelim 😊

Two Factor Authentication Yazımına Başlayalım

Artık Two Auth Factor konusunu kavradığımıza göre dostlarım gelelim bu algoritmanın yazım işlemine 😊. Öncelikle dostlarım bir veri tabanı oluşturalım. Ben two-factor-auth isimli bir veri tabanı oluşturup içerisine de users isimli bir tablo yerleştirdim. Bu tablomun içerisine de örnek olarak 3 tane kullanıcı ekledim. Hemen bunlara bakacak olursak dostlarım

şeklinde 3 adet kullanıcı mevcut. Şifreler de bu arada önce md5 leyip sonra sha1 formatına aldım. Bu kısmı da kaptığımıza göre dostlarım gelelim artık veri tabanı bağlantı dosyamıza. Öncelikle baglan.php isminde bir dosya oluşturduk ve

<?php

// SESSION TUTACAGIMIZ ICIN
ob_start();
session_start();

try {
    $db = new PDO("mysql:host=localhost;dbname=two-factor-auth;charset=utf8","root",12345678);
}catch (PDOException $e){
    echo $e->getMessage();
}

şeklinde bağlantı kodlarımızı yazdık. Daha sonrasında SMTP ile kullanıcımıza doğrulama kodunu iletmek için bir paket kurmamız lazım. Bunun için de projemizin kurulu oldugu dizine gelip console'u açalım ve

composer require phpmailer/phpmailer

kodunu yazıp projemize PHPMailer kütüphanemizi kuralım. Bu kurulumu yaptıktan sonra dostlarım bir tane index.php isimli bir dosya oluşturalım. Bu kısımda kulllanıcımızın giriş yapma formunu yazalım. Kodlar

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <title>Çift Faktörlü Giriş | MFSoftware Blog</title>
</head>
<body>

<div class="container justify-content-center w-50" style="margin-top: 9%">
    <div class="row">

        <?php if (isset($_GET['durum']) && $_GET['durum'] == "bos") { ?>
            <div class="col-md-12 alert alert-danger text-center">
                Giriş Alanları Boş Olamaz
            </div>
        <?php } ?>

        <?php if (isset($_GET['durum']) && $_GET['durum'] == "kullaniciyok") { ?>
            <div class="col-md-12 alert alert-danger text-center">
                Kullanıcı Yok
            </div>
        <?php } ?>

        <?php if (isset($_GET['durum']) && $_GET['durum'] == "no") { ?>
            <div class="col-md-12 alert alert-danger text-center">
                Bir Hata Oluştu. Lütfen Daha Sonra Tekrar Deneyiniz
            </div>
        <?php } ?>

        <div class="col-md-12">
            <div class="card">
                <form method="POST" action="islem.php">
                    <div class="form-group">
                        <label for="exampleInputEmail1">Kullanıcı Adınız</label>
                        <input type="text" class="form-control" name="username" placeholder="Kullanıcı Adınız">
                    </div>
                    <br>
                    <div class="form-group">
                        <label for="exampleInputPassword1">Şifreniz</label>
                        <input type="password" class="form-control" name="password" placeholder="Şifreniz">
                    </div>
                    <br>
                    <button type="submit" name="login" class="btn btn-primary">Giriş Yap</button>
                </form>
            </div>
        </div>
    </div>
</div>


<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
        crossorigin="anonymous"></script>
</body>
</html>

şeklinde giriş yapma formumuzu yazalım. Daha sonra ise doğrulama kodunu gireceğimiz formun tasarımını yazalım. factor.php isimli bir dosya oluşturalım ve

<?php
require_once 'baglan.php';

if (!isset($_SESSION['login'])){
    header("Location: index.php");
}
?>

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <title>Çift Faktörlü Giriş | MFSoftware Blog</title>
</head>
<body>

<div class="container justify-content-center w-50" style="margin-top: 9%">
    <div class="row">

        <?php if (isset($_GET['durum']) && $_GET['durum'] == "bos") { ?>
            <div class="col-md-12 alert alert-danger text-center">
                 İnput Alanı Boş Olamaz
            </div>
        <?php } ?>

        <?php if (isset($_GET['durum']) && $_GET['durum'] == "no") { ?>
            <div class="col-md-12 alert alert-danger text-center">
                Bir Hata Oluştu. Lütfen Daha Sonra Tekrar Deneyiniz
            </div>
        <?php } ?>

        <?php if (isset($_GET['durum']) && $_GET['durum'] == "hatali") { ?>
            <div class="col-md-12 alert alert-danger text-center">
                Doğrulama Kodunuz Yanlış
            </div>
        <?php } ?>

        <div class="col-md-12">
            <div class="card">
                <form method="POST" action="islem.php">
                    <div class="form-group">
                        <label for="exampleInputPassword1">Doğrulama Kodunuz</label>
                        <input type="password" class="form-control" name="code" placeholder="Doğrulama Kodunuz">
                    </div>
                    <br>
                    <button type="submit" name="verify_factor" class="btn btn-primary">Giriş Yap</button>
                </form>
            </div>
        </div>
    </div>
</div>


<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
        crossorigin="anonymous"></script>
</body>
</html>

şeklinde içerisine kodlarımızı yazalım. Login olduğumuzda karşımıza gelecek olan sayfa olan login.php dosyamızı ayarlayalım. Hemen hızlıca onun kodlarını da yazalım dostlarım

<?php

require_once 'baglan.php';
if (!isset($_SESSION['factor'])){
    header("Location: factor.php");
    exit;
}

if (!isset($_SESSION['login'])){
    header("Location: index.php");
    exit;
}

?>

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Çift Faktörlü Giriş | MFSoftware Blog</title>
</head>
<body>
    Giriş Yapıldıııı !!
    <br><br>
    <a href="logout.php">Çıkış Yap</a>
</body>
</html>

şeklinde kodlarımızı yazdık. Çıkış yapma kodlarımızı da hemen yazalım dostlarım. Kodlama kısmımıza gelip

<?php

session_start();
ob_start();
session_destroy();
header("Location: index.php");

şeklinde logout.php dosyamızın içeriğini de yazmış olduk dostlarım 😊. Gelelim en ama en güzel kısım olan ve en karmaşık (sakın gözünüz korkmasın dostlarım olaylar çok basit 😊) olan dosyamız olan index.php dosyamızı yazma işlemimize gelelim. Hemen bir islem.php isminde bir dosya yazalım ve içerisini

<?php

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require_once('vendor/autoload.php');

require_once 'baglan.php';

// GİRİŞ KODLARI
if (isset($_POST['login'])) {
    if ($_POST['username'] == "" || $_POST['password'] == "") {
        header("Location: index.php?durum=bos");
    } else {
        $username = $_POST['username'];
        $password = sha1(md5($_POST['password']));

        $kullanici = $db->prepare("SELECT * FROM users WHERE username=:username AND password=:password");
        $kullanici->execute(array(
            "username" => $username,
            "password" => $password
        ));
        $kullanici_cek = $kullanici->fetch(PDO::FETCH_ASSOC);

        if ($kullanici->rowCount()==1) {
            $kullanici_cek = $kullanici->fetch(PDO::FETCH_ASSOC);
            $_SESSION['login'] = true;
            $_SESSION['username'] = $username;
            $_SESSION['email'] = $kullanici_cek['email'];

            // KULLANICIYA DOGRULAMA KODUNU GONDERELIM
            $code = time();  // kullanıcıya gidecek kod

            $mail = new PHPMailer(true);
            try {
                $mail->SMTPDebug = 2;   // 1 hata ve mesaj verdirir, 2 sadece mesaj verdirir
                $mail->isSMTP();  // gonderilecek mailin bir smtp maili olduğunu programa söylüyoruz
                $mail->Host = "smtp.mailtrap.io";  // mail host adresi
                $mail->SMTPAuth = true;   // smtp de mail doğrulaması yapılacağını sisteme belirtmiş olduk
                $mail->Username = "";  // mailiniz
                $mail->Password = "";  // sifreniz
                $mail->SMTPSecure = "tls";  // smtp güvenliği
                $mail->Port = "2525";  // smtp port (465 güvenlikli)  (gmail kullanacaksanız 587 yapabilirsiniz)

                $mail->setFrom("mail_adresiniz", "adiniz_soyadiniz");
                $mail->addAddress($kullanici_cek['email']);  // mail kime gidecek

                // $mail->addBCC();
                // $mail->addCCC();   // bu ikisi çoklu mail gönderileceği durumlarda kullanılabilir

                $mail->isHTML();  // mailin html formatında gönderileceği bilgisi
                $mail->CharSet = "UTF-8"; // kkarakter seti
                $mail->Subject = "Çift Doğrulamalı Giriş";
                $mail->Body = "Sayın Kullanıcı. Sistemimize " . $code . " Giriş kodunu kullanarak girebilirsiniz";

                if ($mail->send()) {
                    // mail gönderme başarılı ise yapılacak işlemler
                    $guncelle = $db->prepare("UPDATE users SET code=:code WHERE username=:username AND password=:password");
                    $update = $guncelle->execute(array(
                        "code" => $code,
                        "username" => $username,
                        "password" => $password
                    ));

                    if ($update) {
                        header("Location: factor.php");
                    } else {
                        header("Location: index.php?durum=hata");
                    }
                } else {
                    // mail gönderme başarısız ise yapılacak işlemler
                    header("Location: index.php?durum=hata");
                }
            } catch (Exception $e) {
                echo $e->getMessage();
            }
        } else {
            header("Location: index.php?durum=kullaniciyok");
        }
    }
}


// DOĞRULAMA KODU
if (isset($_POST['verify_factor'])) {
    if ($_POST['code'] == "") {
        header("Location: factor.php?durum=bos");
    } else {
        $username = $_SESSION['username'];
        $email = $_SESSION['email'];
        $code = $_POST['code'];


        $kullanici = $db->prepare("SELECT * FROM users WHERE username=:username AND email=:email AND code=:code");
        $kullanici->execute(array(
            "username" => $username,
            "email" => $email,
            "code" => $code
        ));
        if ($kullanici->rowCount()==1){
            // KULLANICI VAR İSE
            $guncelle = $db->prepare("UPDATE users SET code=:code WHERE username=:username AND email=:email");
            $update = $guncelle->execute(array(
                "username" => $username,
                "email" => $email,
                "code" => ""
            ));

            if ($update){
                $_SESSION['factor'] = true;
                header("Location: login.php");
            }else{
                header("Location: factor.php?durum=no");
            }
        }else{
            // KULLANICI YOK ISE
            header("Location: factor.php?durum=hatali");
        }
    }
}

şeklinde kodlarımızı yazdık dostlarım 😊. 

İşte bütün işlem bu kadar dostlarım. Artık iki faktörlü doğrulama işlemimiz hazır. Bu yapıyı sistemlerinizde gereksinimlerinize göre değiştirip rahat rahat değiştirip kullanabilirsiniz 😊. Bütün olay bu 😊.

Yazımızın sonuna da geldiğimizi artık hepimiz sezdik dostlarım 😊. Bu yazımda elimden geldiğince dilim döndüğünce sizlere Two Factor Authentication olayını PHP programlama dili üzerinde elimden geldiğince, dilim döndüğünce anlatmaya çalıştım. Umarım faydalı olmuşumdur. Eksik veya hatalı bir anlatım yapmış isem benimle iletişime geçmekten çekinmeyin 😊. Konu başlarda biraz karmaşık veya zor gelmiş olabilir dostlarım anlıyorum. Özellikle öğrenme süreci içerisinde bu olaylarla karşılaşmamız son derece normaldir. Bu süreçte yapacağınız tek şey her yazımın altında da dediğim gibi "İstikrarlı ve Azimli Olmalısınız, Bolca Pratik Yapmalısınız". Bu dediklerimi hayat felsefeniz yaptığınız sürece başarı sizler için kaçınılmaz olacaktır 😊

Hayallerinizi gerçekleştirmeniz ve güzel yerlere gelmeniz dileklerimle... İyi çalışmalar dilerim 😊

Muhammed Fatih BAĞCIVAN
Yazar Hakkında

Kendi Halinde Bir Backend Developer

Önceki YazıPHP Excell'e Veri Aktarma
Sonraki YazıLaravel Üzerinde Eloquent ORM ile Veri Ekleme
Yorumlar (2)
Yavuz Seliö
26.12.2021

Gerçekten türkçe kaynak olarak çok iyi bir yazı olmuş ellerine sağlık 👏👏👏👏

Volkan kaymak
27.12.2021

Türkçe kaynak bulamayanlar çok iyi bir yazı ellerinize sağlık. Denedim yaptım oldu içeriğini kendinize göre değiştirip daha da yüksek halde güvenliğinizi arttırabilirsiniz.

Yorum Yapabilirsiniz