İçeriğe geç
Muhammet Şafak
Framework & Kütüphane 3 dk okuma

Laravel 5.2: çoklu kimlik doğrulama ve route grupları

Laravel 5.2 ile birden fazla kullanıcı tipini tek uygulamada nasıl yönettiğimi; guard ve route gruplarını anlatıyorum.


Geliştirdiğim projelerden birinde hem normal kullanıcılar hem de yöneticiler için ayrı giriş ekranları, ayrı paneller ve ayrı yetkilendirme kuralları gerekmişti. Laravel 5.1’de bunu biraz ellemecilik yaparak çözmüştüm; özel bir middleware yazmıştım, oturumları ayrı tutmak için özel anahtarlar kullanmıştım. Çalışıyordu ama temiz değildi.

Laravel 5.2, tam bu ihtiyacı karşılayan çoklu kimlik doğrulama desteğini getirdi. Birkaç gündür bunu incelemedeyim; bu yazıda öğrendiklerimi özetliyorum.

Guard kavramı nedir?

Guard, Laravel’in kimlik doğrulama sisteminin, “bu isteği hangi kullanıcı tablosuna göre doğrulayacağız?” sorusunu yanıtlayan bileşenidir.

Laravel 5.2’den önce uygulama genelinde tek bir guard vardı ve bu users tablosuna bakıyordu. Artık config/auth.php dosyasında birden fazla guard tanımlanabiliyor:

// config/auth.php

'guards' => [
    'web' => [
        'driver'   => 'session',
        'provider' => 'users',
    ],

    'admin' => [
        'driver'   => 'session',
        'provider' => 'admins',
    ],
],

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model'  => App\User::class,
    ],

    'admins' => [
        'driver' => 'eloquent',
        'model'  => App\Admin::class,
    ],
],

Bu tanımla web guard users tablosuna, admin guard ise admins tablosuna bakıyor. Her iki guard da bağımsız oturum tutabiliyor; birinde giriş yapmak diğerini etkilemiyor.

Route gruplarıyla ayırmak

Guard’ları tanımladıktan sonra, hangi rotanın hangi guard’la korunanacağını belirtmek gerekiyor. Bunu route grubu middleware’i ile yapıyorum:

// app/Http/routes.php

// Normal kullanıcı rotaları
Route::group(['middleware' => 'auth:web', 'prefix' => 'hesabim'], function () {
    Route::get('/', 'AccountController@index');
    Route::get('profil', 'AccountController@profile');
});

// Yönetici rotaları
Route::group(['middleware' => 'auth:admin', 'prefix' => 'yonetim'], function () {
    Route::get('/', 'Admin\DashboardController@index');
    Route::get('kullanicilar', 'Admin\UserController@index');
});

auth:web ve auth:admin sözdizimi, auth middleware’ine hangi guard’ı kullanacağını söylüyor. Artık /hesabim altındaki rotalar web guard’ına, /yonetim altındakiler ise admin guard’ına göre doğrulanıyor.

Controller’da guard belirtmek

Controller içinden de doğrudan guard belirterek giriş kontrolü yapılabiliyor:

<?php

namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class DashboardController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:admin');
    }

    public function index()
    {
        $admin = auth()->guard('admin')->user();

        return view('admin.dashboard', compact('admin'));
    }
}

auth()->guard('admin')->user() çağrısı, admin guard üzerinden oturum açmış kullanıcıyı döndürüyor. Normal auth()->user() hâlâ varsayılan guard’ı (web) kullanıyor.

Giriş controller’larını ayırmak

Kimlik doğrulama akışı için de ayrı controller’lar yazmak gerekiyor. artisan make:auth komutu standart Auth\LoginController oluşturuyor; admin için bunu kopyalayıp guard metodunu ezerek özelleştiriyorum:

<?php

namespace App\Http\Controllers\Admin\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    use AuthenticatesUsers;

    protected $redirectTo = '/yonetim';

    protected function guard()
    {
        return auth()->guard('admin');
    }

    public function showLoginForm()
    {
        return view('admin.auth.login');
    }
}

guard() metodunu ezerek auth:admin guard’ının kullanılmasını sağlıyorum. Gerisi AuthenticatesUsers trait’inin işi.

Parola sıfırlama tuzağı

Bu yaklaşımın iyi çalıştığı yer oturum açma ve kontrol akışları. Ama parola sıfırlama, dikkat edilmezse sorun çıkarabiliyor. Laravel’in varsayılan parola sıfırlama akışı users tablosuna ve web guard’a bağlı çalışıyor. Admin için bunu ayrıca yapılandırmak gerekiyor.

config/auth.php dosyasında passwords bölümünü düzenleyerek admin için ayrı bir broker tanımlanabiliyor:

'passwords' => [
    'users' => [
        'provider' => 'users',
        'table'    => 'password_resets',
        'expire'   => 60,
    ],
    'admins' => [
        'provider' => 'admins',
        'table'    => 'password_resets',
        'expire'   => 60,
    ],
],

Bunu atladığınızda admin parola sıfırlama e-postası yanlış tabloya bakıyor ya da hiç çalışmıyor; bu hatayı geliştirme ortamında değil, test aşamasında fark ettim.

Gözlemlerim

Bu yaklaşımın en güzel yanı, iki kullanıcı tipini birbirinden izole etmesi. Admin oturumu, normal kullanıcı oturumunu hiç etkilemiyor. Aynı tarayıcıda her iki hesapla aynı anda giriş yapılabiliyor; bu özellikle geliştirme ve test sırasında çok işe yarıyor.

5.2 bu ihtiyacı çok daha temiz bir API ile çözüyor. Önceki çözümüme kıyasla ortaya çıkan kod hem daha az, hem de Laravel’in kendine özgü yapısına daha uyumlu.

Bir not daha: birden fazla guard kullanırken middleware sırasına dikkat etmek gerekiyor. Bir rota hem auth:web hem de başka bir middleware alıyorsa, sıralama önemli olabiliyor. Örneğin kullanıcının giriş yapmış olup olmadığını kontrol eden middleware, sadece giriş yapılmış kullanıcılara özgü başka işlemler yapan middleware’den önce gelmeli; aksi hâlde henüz kimliği doğrulanmamış bir istek, yanlış middleware’e çarpabilir. Küçük bir proje için bu sıralama fark yaratmayabilir; ama çok adımlı kontroller ekledikçe bu davranışı bir kez test etmek iyi alışkanlık.

5.2’den önce aynı sorunu çözmek için yazdığım el yapımı middleware’i incelediğimde, framework’ün bu işi ne kadar daha doğru modellediğini gördüm. Kendi yazdığım çözümde iki guard aynı oturum anahtarını kullandığı için admin giriş yaptığında kullanıcı oturumu da karışıyordu — nadir ama gerçek bir hataydı. Laravel’in guard başına ayrı oturum yönetimi bunu tamamen ortadan kaldırıyor.

Etiketler: #Laravel
Paylaş:

İlgili Yazılar

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi