مقدمة في المصادقة في Laravel
المصادقة هي عملية التحقق من هوية المستخدم، بينما التفويض يحدد الإجراءات التي يمكن للمستخدم القيام بها. يوفر Laravel نظام مصادقة كامل جاهز للاستخدام، مما يسهل تنفيذ تسجيل دخول آمن وتسجيل مستخدمين والتحكم في الوصول.
أدوات البداية للمصادقة في Laravel
يوفر Laravel عدة حزم بداية للمصادقة:
- Laravel Breeze: هيكل مصادقة بسيط مع قوالب Blade
- Laravel Jetstream: مصادقة كاملة المميزات مع دعم الفرق
- Laravel Fortify: واجهة خلفية للمصادقة بدون واجهة أمامية (صديقة لـ API)
- Laravel Sanctum: مصادقة برموز API لتطبيقات SPA
ملاحظة: Laravel Breeze هو الخيار الأبسط ومثالي للتعلم. يتضمن تسجيل الدخول، التسجيل، إعادة تعيين كلمة المرور، التحقق من البريد الإلكتروني، وتأكيد كلمة المرور.
تثبيت Laravel Breeze
لتثبيت Laravel Breeze في تطبيق Laravel جديد:
# تثبيت Breeze عبر Composer
composer require laravel/breeze --dev
# تثبيت هيكل Breeze
php artisan breeze:install
# الخيارات:
# - Blade (افتراضي)
# - React
# - Vue
# - API (للتطبيقات بدون واجهة أمامية)
# ترجمة الملفات
npm install
npm run dev
# تشغيل الترحيلات
php artisan migrate
بعد التثبيت، يوفر Breeze المسارات التالية تلقائياً:
// مسارات المصادقة
/login - نموذج تسجيل الدخول
/register - نموذج التسجيل
/forgot-password - طلب إعادة تعيين كلمة المرور
/reset-password - نموذج إعادة تعيين كلمة المرور
/verify-email - التحقق من البريد الإلكتروني
/confirm-password - تأكيد كلمة المرور
/logout - تسجيل الخروج (POST)
// المسارات المحمية
/dashboard - لوحة تحكم المستخدم (يتطلب المصادقة)
نموذج المستخدم
يأتي Laravel مع نموذج User ينفذ عقود المصادقة:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed', // Laravel 10+
];
}
نصيحة: نموذج User يمتد من Authenticatable، والذي يوفر جميع وظائف المصادقة. السمة Notifiable تسمح بإرسال الإشعارات للمستخدمين.
المصادقة اليدوية
يمكنك مصادقة المستخدمين يدوياً بدون استخدام حزم البداية:
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
public function showLoginForm()
{
return view('auth.login');
}
public function login(Request $request)
{
// التحقق من البيانات
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
// محاولة المصادقة
if (Auth::attempt($credentials, $request->boolean('remember'))) {
// إعادة توليد الجلسة لمنع الاختطاف
$request->session()->regenerate();
return redirect()->intended('dashboard');
}
// فشلت المصادقة
return back()->withErrors([
'email' => 'بيانات الاعتماد المقدمة غير متطابقة مع سجلاتنا.',
])->onlyInput('email');
}
public function logout(Request $request)
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}
حماية المسارات بالمصادقة
استخدم middleware auth لطلب المصادقة:
<?php
use App\Http\Controllers\DashboardController;
use Illuminate\Support\Facades\Route;
// حماية مسار واحد
Route::get('/dashboard', [DashboardController::class, 'index'])
->middleware('auth');
// حماية عدة مسارات بالمجموعة
Route::middleware(['auth'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
Route::get('/profile', [ProfileController::class, 'show']);
Route::get('/settings', [SettingsController::class, 'index']);
});
// حماية المسارات في constructor المتحكم
class DashboardController extends Controller
{
public function __construct()
{
$this->middleware('auth');
// باستثناء دوال معينة
$this->middleware('auth')->except(['index', 'show']);
// دوال معينة فقط
$this->middleware('auth')->only(['create', 'store', 'edit', 'update']);
}
}
الوصول إلى المستخدم المصادق
استرجع المستخدم المصادق حالياً بطرق متعددة:
<?php
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
// استخدام Auth facade
$user = Auth::user();
$id = Auth::id();
// التحقق من المصادقة
if (Auth::check()) {
// المستخدم مسجل الدخول
}
// استخدام كائن Request
public function index(Request $request)
{
$user = $request->user();
}
// استخدام دالة مساعدة auth()
$user = auth()->user();
$id = auth()->id();
// في عروض Blade
@auth
<p>مرحباً، {{ auth()->user()->name }}</p>
@endauth
@guest
<p>يرجى تسجيل الدخول</p>
@endguest
التحقق من البريد الإلكتروني
يوفر Laravel وظيفة التحقق من البريد الإلكتروني المدمجة:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
// تنفيذ عقد MustVerifyEmail
class User extends Authenticatable implements MustVerifyEmail
{
// ...
}
// في routes/web.php - حماية المسارات مع verified middleware
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
});
ملاحظة: التحقق من البريد الإلكتروني يتطلب تكوين البريد في ملف .env. للتطوير المحلي، استخدم Mailtrap أو log driver.
إعادة تعيين كلمة المرور
Laravel Breeze يتضمن إعادة تعيين كلمة المرور جاهزة. إليك كيفية عملها يدوياً:
<?php
use Illuminate\Support\Facades\Password;
// إرسال رابط إعادة تعيين كلمة المرور
public function sendResetLink(Request $request)
{
$request->validate(['email' => 'required|email']);
$status = Password::sendResetLink(
$request->only('email')
);
return $status === Password::RESET_LINK_SENT
? back()->with(['status' => __($status)])
: back()->withErrors(['email' => __($status)]);
}
// إعادة تعيين كلمة المرور
public function resetPassword(Request $request)
{
$request->validate([
'token' => 'required',
'email' => 'required|email',
'password' => 'required|min:8|confirmed',
]);
$status = Password::reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function ($user, $password) {
$user->password = $password;
$user->save();
}
);
return $status === Password::PASSWORD_RESET
? redirect()->route('login')->with('status', __($status))
: back()->withErrors(['email' => [__($status)]]);
}
حراس المصادقة (Guards)
الحراس يحددون كيفية مصادقة المستخدمين لكل طلب. يدعم Laravel حراساً متعددة لأنواع مختلفة من المستخدمين:
// config/auth.php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],
];
استخدام حراس مختلفة:
<?php
// استخدام حارس معين
if (Auth::guard('admin')->attempt($credentials)) {
// تمت مصادقة المشرف
}
// تسجيل خروج من حارس معين
Auth::guard('admin')->logout();
// حماية المسارات بحارس معين
Route::middleware(['auth:admin'])->group(function () {
Route::get('/admin/dashboard', [AdminController::class, 'index']);
});
// الحصول على المستخدم من حارس معين
$admin = Auth::guard('admin')->user();
التفويض الأساسي مع البوابات (Gates)
التفويض يحدد ما يمكن للمستخدمين المصادقين القيام به. البوابات هي closures بسيطة لمنطق التفويض:
<?php
// app/Providers/AuthServiceProvider.php
namespace App\Providers;
use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
public function boot(): void
{
// تعريف بوابة
Gate::define('update-post', function (User $user, Post $post) {
return $user->id === $post->user_id;
});
// بوابة بدون نموذج (فحص خاصية المستخدم)
Gate::define('manage-users', function (User $user) {
return $user->is_admin;
});
}
}
// استخدام البوابات في المتحكمات
public function update(Request $request, Post $post)
{
Gate::authorize('update-post', $post);
// بديل: يرمي 403 إذا كان غير مصرح
if (Gate::denies('update-post', $post)) {
abort(403);
}
// أو استخدم allows()
if (Gate::allows('update-post', $post)) {
// تحديث المنشور
}
}
// في عروض Blade
@can('update-post', $post)
<a href="{{ route('posts.edit', $post) }}">تعديل</a>
@endcan
نصيحة: البوابات هي الأفضل لفحوصات التفويض البسيطة. لمنطق تفويض أكثر تعقيداً، استخدم السياسات (Policies) التي سنغطيها في الدرس التالي.
تمرين 1: إنشاء نظام مصادقة
قم بتثبيت Laravel Breeze في مشروع Laravel جديد وخصص نموذج التسجيل ليتضمن حقل "phone".
- ثبت Breeze باستخدام
composer require laravel/breeze --dev
- شغل
php artisan breeze:install
- أضف عمود "phone" إلى ترحيل users
- حدّث عرض نموذج التسجيل
- حدّث مصفوفة fillable في نموذج User
- اختبر التسجيل مع الحقل الجديد
تمرين 2: تنفيذ مصادقة مخصصة
أنشئ متحكم تسجيل دخول مخصص بدون استخدام Breeze يصادق المستخدمين باسم المستخدم بدلاً من البريد الإلكتروني.
- أنشئ LoginController مع دوال showLoginForm() و login()
- تحقق من حقول username و password
- استخدم Auth::attempt() مع حقل username
- أعد توليد الجلسة عند النجاح
- أعد التوجيه إلى لوحة التحكم أو أرجع أخطاء التحقق
- أنشئ عرض تسجيل الدخول المقابل
تمرين 3: مصادقة متعددة الحراس
قم بإعداد نظام مصادقة متعدد الحراس مع حراس منفصلين للمستخدمين العاديين والمشرفين.
- أنشئ نموذج Admin والترحيل الخاص به
- أضف حارس "admin" في config/auth.php
- أنشئ متحكم مصادقة المشرف
- أضف مسارات المشرف المحمية بـ auth:admin middleware
- اختبر تسجيل الدخول كمستخدم وكمشرف
- تأكد من أن الحراس لا يتداخلون مع بعضهم البعض
الملخص
في هذا الدرس، تعلمت:
- حزم بداية المصادقة في Laravel (Breeze، Fortify، Jetstream)
- تثبيت واستخدام Laravel Breeze
- المصادقة اليدوية باستخدام Auth facade
- حماية المسارات باستخدام auth middleware
- الوصول إلى المستخدمين المصادقين
- التحقق من البريد الإلكتروني وإعادة تعيين كلمة المرور
- حراس المصادقة لأنواع متعددة من المستخدمين
- التفويض الأساسي باستخدام البوابات
الدرس التالي: سنتعمق أكثر في التفويض باستخدام السياسات ونتعلم عن تخصيص middleware.