Laravel'de Çoklu Yetkilendirme(Authorization) İşlemleri

Normal şartlarda laravel sabit kimlik doğrulamasına sahiptir. Bunun ile birlikte yönetici ve kullanıcılar aynı kimlik yönetimi ile yönetilebilmektedir. Peki şimdi şu soruyu sorabilirsiniz; "O zaman neden buna ihtiyacımız olucak?" Aslında buna çok ihtiyacımız yok, bu gibi durumda User modeli üzerinde hasRole()  methodu ile farklı kimlikleri ayrıştırıp ona göre gösterim işlemlerimizi yapabiliyoruz fakat ben bunu yapmak istemiyorum ve "benim g.tüm kalkık abi, ben üyeler ile aynı tabloda olacak adam mıyım" diyorsan doğru makaleyi okuyorsun demektir cancağızım. Şimdi burada yapacağımız işlemler laravelde custom authentication olarak adlandırılmaktadır.  Şimdi anahtar kelimemizide konuya dahil edip, bugünlük yapmamız gereken seo çalışmamızı da yapmış olmamın verdiği heyecan ile bismillah deyip işlemlere birlikte geçelim. Ben burada yönetici olarak custom authentication oluşturacağım. Siz daha fazla kimlik doğrulama isterseniz buradaki adımları çoğaltarak kullanabilirsiniz.

İlk işlem olarak eğer laravel projemizde doğrulama(auth) işlemlerinin iskelet yapılandırmasını yapmadı isek onu yapıyoruz. Bu işlemi daha önce yaptıysan es geçebilirsin burayı.
php artisan make:auth

Şimdi ise ilk olarak veritabanı ile bağlantı kuracak olan model yapımızı artisan yardımıyla oluşturuyoruz.
php artisan make:model Admin -m

Modelimiz oluştu ve içeriğinde gerekli olan alanları dolduruyoruz. Ben User modelini kopya ederek gerekli alanları ayarlamıştım.
namespace App;


use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable
{
use Notifiable;

protected $guarded = 'admin';

protected $table = 'admins';

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];

/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token'
];

public $timestamps = false;
}

Modelimiz ile şimdilik işimiz bittikten sonra migration ile admins tablomuzu oluşturabiliriz veya iskelet yapımızı kurduğumuzda oluşan users migration ile kolayca türetebiliriz. Üşendim ben derseniz buradan dosyayı veriyorum. Dosyayı oluşturduktan sonra terminalden php artisan make migration komutunu çalıştırıp tabloyu da oluşturuyoruz.
use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateAdminsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('admins', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email');
$table->string('password');
$table->rememberToken();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('admins');
}
}

Şimdi model dosyamız ve tablomuz kurulu olduğuna göre laraveldeki middleware yapılarına yani controller ile view arasındaki ara katmanımız için gerekli kimlik bilgilerini tanıtacağız. Proje dizininde bulunan config/auth.php dosyasını açıyoruz ve guards, providers kısımlarını düzeltiyoruz.
'guards' => [

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

'api' => [
'driver' => 'token',
'provider' => 'users',
],

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

'admin-api' => [
'driver' => 'token',
'provider' => 'admins',
],
],

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

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

Ayarlamamızı yaptıktan sonra yönetici(admin) girişi için view işlemizde form kısmını bu şekilde düzenliyoruz. Kullanıcı girişiyle aynı olduğu için o formun aynısını kopyaladım sadece gerekli alan action kısmı düzelttim. Buradaki dikkat etmeniz gereken en önemli şey ise belirttiğimiz route isminin sende de olması yada senin bunu düzeltmendir.
<form id="admin_login" method="POST" action="{{ route('admin.login.submit') }}">

@csrf
<div class="input-group"> <span class="input-group-addon"> <i class="zmdi zmdi-account"></i> </span>
<div class="form-line">
<input type="email" class="form-control" name="email" placeholder="E-Posta Adresi" value="{{ old('email') }}" required autofocus>
</div>
@if ($errors->has('email'))
<span class="text-danger"><strong>{{ $errors->first('email') }}</strong></span>
@endif
</div>

<div class="input-group"> <span class="input-group-addon"> <i class="zmdi zmdi-lock"></i> </span>
<div class="form-line">
<input type="password" class="form-control" name="password" placeholder="Şifre" required>
</div>
</div>
<div>
<div class="">
<input type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }} id="rememberme" class="filled-in chk-col-pink">
<label for="rememberme">Beni Hatırla</label>
</div>
<div class="text-center">
<button type="submit" class="btn btn-raised waves-effect g-bg-cyan">Giriş Yap</button>
</div>
</div>
</form>

Şimdi view dosyamızı oluşturduk ama bunun bir controller dosyası da olmalı ki elini kolunu sallayan herkes yönetici sayfamıza erişemesin. Terminale php artisan make:controller Admin/Admin yazarak Admin controller dosyamızı oluşturuyoruz ve içeriğini böyle düzenliyoruz.
namespace App\Http\Controllers\Admin;


use App\Http\Controllers\Controller,
App\Setting,
Illuminate\Support\Facades\Validator,
Illuminate\Http\Request,
Illuminate\Support\Facades\Auth,
Illuminate\Support\Facades\Hash;

class Admin extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth:admin');
}

/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
return view('admin.dashboard');
}

public function logout(Request $request)
{
Auth::guard('admin')->logout();
$request->session()->flush();
$request->session()->regenerate();
return redirect()->guest(route('admin.login'));
}
}

Tamam yönetici sayfamız için gerekli controller oluşturduk fakat login işlemleri için de controller ihtiyacımız var hemen terminalden php artisan make:controller Admin/AdminLogin çalıştırıyoruz. Ve içeriğini düzenliyoruz.


namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;
use App\Setting;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;

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

public function login()
{
$setting = Setting::find(1);
return view('admin.login', compact('setting'));
}

public function loginForm(Request $request)
{
$this->validate($request, [
'email' => 'required|email',
'password' => 'required'
]);

if (Auth::guard('admin')->attempt(['email' => $request->email, 'password' => $request->password], $request->remember))
{
return redirect()->intended(route('admin.dashboard'));
}

return redirect()->back()->withInput($request->only('email', 'remember'));
}
}

Yazmaktan yoruldum vallahi ama senin değer cancağızım. Şimdi route işlemlerini yapıyoruz. Bunun için proje dizininde routes/web.php dosyamızı açıyoruz. Ve en altına bu yönlendirmeleri ekliyoruz. Burada route group methodundan yararlandık çünkü sürekli admin, admin yazmaktansa group içinde belirttik ona ait işlemleri.
Route::group(['prefix' => 'admin'], function() {

# Login Page
Route::get('/login', 'Admin\AdminLogin@login')->name('admin.login');

# Login POST Page
Route::post('/login', 'Admin\AdminLogin@loginForm')->name('admin.login.submit');

# Admin Dashboard
Route::get('/', 'Admin\Admin@index')->name('admin.dashboard');

# Admin Logout
Route::post('/logout', 'Admin\Admin@logout')->name('admin.logout');
});

Şimdiye buraya kadar her şey tamamsa kardeşim, ilk olarak Illuminate\Foundation\Exceptions\Handler sınıfımıza ulaşıp unauthenticated() methodumuzu bu şekilde değiştiriyoruz. Bu doğru middleware yönlendirmeleri için gerekli kısımdır. Bu kısımda dikkat etmemiz gereken nokta ise route isimlerini doğru girmemiz olucaktır yoksa hata alırız.
protected function unauthenticated($request, AuthenticationException $exception)

{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
$guard = array_get($exception->guards(), 0);
switch ($guard) {
case 'admin':
$login = 'admin.login';
break;
default:
$login = 'login';
break;
}
return redirect()->guest(route($login));
}

Son olarakta başarılı şekilde kimliğimi doğrulandıktan sonra middleware abimizin bizi doğru sayfaya tükürmesini sağlayacak ayarlarını app/Http/Middleware/RedirectIfAuthenticated.php dosyasında handle methodunu düzenleyerek yapıyoruz. Az önceki düzenlemede söylediğim gibi burada dikkat etmemiz gereken can alıcı nokta route isimlerinin doğru bir şekilde ayarlanmasıdır.
public function handle($request, Closure $next, $guard = null)

{
switch ($guard) {
case 'admin':
if (Auth::guard($guard)->check()) {
return redirect()->route('admin.dashboard');
}
break;
default:
if (Auth::guard($guard)->check()) {
return redirect('/');
}
break;
}
return $next($request);
}

Her şey bu kadar cancağızım. Benim bu işlemleri anlayıp ve geliştirmemi sağlayan DevMarketer kanalındaki J. Alexander Curtis abimize teşekkürlerimizi sunuyoruz.