أساسيات PHP
الصفحات المحمية والتصريح
الصفحات المحمية والتصريح
الآن بعد أن أصبح لدينا أنظمة التسجيل وتسجيل الدخول، نحتاج إلى حماية صفحات معينة من الوصول غير المصرح به وتنفيذ التصريح القائم على الأدوار. في هذا الدرس، سنتعلم كيفية إنشاء صفحات محمية، تنفيذ التحكم في الوصول، وإدارة أذونات المستخدم.
إنشاء صفحة محمية
لنقم بإنشاء نظام وسيط لحماية الصفحات التي تتطلب المصادقة:
auth_middleware.php:
<?php
/**
* وسيط المصادقة
* قم بتضمين هذا في أعلى أي صفحة محمية
*/
// بدء الجلسة إذا لم تكن قد بدأت بالفعل
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
/**
* يتطلب المصادقة
* يعيد التوجيه إلى صفحة تسجيل الدخول إذا لم يكن المستخدم مسجلاً للدخول
*/
function requireAuth() {
if (!isset($_SESSION['user_id'])) {
// تخزين URL المطلوب لإعادة التوجيه بعد تسجيل الدخول
$_SESSION['redirect_after_login'] = $_SERVER['REQUEST_URI'];
// إعادة التوجيه إلى صفحة تسجيل الدخول
header('Location: /login.php');
exit;
}
// التحقق من صحة الجلسة
validateSession();
}
/**
* التحقق من أمان الجلسة
*/
function validateSession() {
// التحقق من عمر الجلسة (تنتهي بعد ساعتين من عدم النشاط)
if (isset($_SESSION['last_activity'])) {
$inactive_time = time() - $_SESSION['last_activity'];
if ($inactive_time > 7200) { // ساعتان
session_unset();
session_destroy();
header('Location: /login.php?session_expired=1');
exit;
}
}
// تحديث وقت النشاط الأخير
$_SESSION['last_activity'] = time();
// التحقق من وكيل المستخدم
$current_ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
if (isset($_SESSION['user_agent'])) {
if ($_SESSION['user_agent'] !== $current_ua) {
session_unset();
session_destroy();
header('Location: /login.php?security_error=1');
exit;
}
} else {
$_SESSION['user_agent'] = $current_ua;
}
}
/**
* الحصول على معلومات المستخدم الحالي
*/
function getCurrentUser() {
return [
'id' => $_SESSION['user_id'] ?? null,
'username' => $_SESSION['username'] ?? null,
'email' => $_SESSION['email'] ?? null,
'full_name' => $_SESSION['full_name'] ?? null,
'role' => $_SESSION['role'] ?? 'user'
];
}
/**
* التحقق من تسجيل دخول المستخدم
*/
function isLoggedIn() {
return isset($_SESSION['user_id']);
}
?>
التصريح القائم على الأدوار
لنقم بتنفيذ نظام التحكم في الوصول القائم على الأدوار لإدارة أذونات المستخدمين المختلفة:
إضافة عمود الدور إلى جدول المستخدمين:
ALTER TABLE users
ADD COLUMN role ENUM('user', 'admin', 'moderator') DEFAULT 'user' AFTER is_active;
authorization.php:
<?php
/**
* وظائف التصريح
* قم بتضمين هذا للتحكم في الوصول القائم على الأدوار
*/
require_once 'auth_middleware.php';
/**
* الحصول على دور المستخدم من قاعدة البيانات
*/
function getUserRole($pdo, $user_id) {
$stmt = $pdo->prepare('SELECT role FROM users WHERE id = ?');
$stmt->execute([$user_id]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result['role'] ?? 'user';
}
/**
* يتطلب دور معين
* يعيد التوجيه مع خطأ إذا لم يكن لدى المستخدم الدور المطلوب
*/
function requireRole($required_role, $pdo) {
requireAuth(); // أولاً التحقق من المصادقة
$user_id = $_SESSION['user_id'];
$user_role = getUserRole($pdo, $user_id);
// تخزين الدور في الجلسة للفحوصات المستقبلية
$_SESSION['role'] = $user_role;
$role_hierarchy = [
'user' => 1,
'moderator' => 2,
'admin' => 3
];
$user_level = $role_hierarchy[$user_role] ?? 0;
$required_level = $role_hierarchy[$required_role] ?? 0;
if ($user_level < $required_level) {
// المستخدم ليس لديه أذونات كافية
http_response_code(403);
die('<h1>403 ممنوع</h1><p>ليس لديك إذن للوصول إلى هذه الصفحة.</p>');
}
}
/**
* التحقق من امتلاك المستخدم لدور معين
*/
function hasRole($role, $pdo) {
if (!isLoggedIn()) {
return false;
}
$user_id = $_SESSION['user_id'];
$user_role = $_SESSION['role'] ?? getUserRole($pdo, $user_id);
$role_hierarchy = [
'user' => 1,
'moderator' => 2,
'admin' => 3
];
$user_level = $role_hierarchy[$user_role] ?? 0;
$required_level = $role_hierarchy[$role] ?? 0;
return $user_level >= $required_level;
}
/**
* التحقق من قدرة المستخدم على تنفيذ إجراء
* تحديد أذونات مخصصة لإجراءات محددة
*/
function can($action, $pdo) {
if (!isLoggedIn()) {
return false;
}
$user_role = $_SESSION['role'] ?? getUserRole($pdo, $_SESSION['user_id']);
// تحديد الأذونات
$permissions = [
'user' => [
'view_profile',
'edit_own_profile',
'view_dashboard'
],
'moderator' => [
'view_profile',
'edit_own_profile',
'view_dashboard',
'moderate_content',
'view_reports'
],
'admin' => [
'view_profile',
'edit_own_profile',
'view_dashboard',
'moderate_content',
'view_reports',
'manage_users',
'view_admin_panel',
'edit_site_settings'
]
];
$user_permissions = $permissions[$user_role] ?? [];
return in_array($action, $user_permissions);
}
?>
مثال على صفحة للمسؤولين فقط
إنشاء صفحة يمكن للمسؤولين فقط الوصول إليها:
admin.php:
<?php
require_once 'authorization.php';
require_once 'db_connect.php';
// يتطلب دور المسؤول
requireRole('admin', $pdo);
// الحصول على المستخدم الحالي
$user = getCurrentUser();
// جلب جميع المستخدمين
$stmt = $pdo->query('
SELECT id, username, email, full_name, role, is_active, created_at, last_login
FROM users
ORDER BY created_at DESC
');
$all_users = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<title>لوحة الإدارة</title>
<style>
body {
font-family: 'Cairo', Arial, sans-serif;
margin: 0;
padding: 0;
background: #f5f5f5;
}
.navbar {
background: #d32f2f;
color: white;
padding: 15px 30px;
display: flex;
justify-content: space-between;
align-items: center;
}
.container {
max-width: 1400px;
margin: 40px auto;
padding: 0 20px;
}
table {
width: 100%;
background: white;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
th, td {
padding: 15px;
text-align: right;
border-bottom: 1px solid #eee;
}
th {
background: #667eea;
color: white;
font-weight: bold;
}
.role-badge {
display: inline-block;
padding: 4px 12px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
}
.role-admin {
background: #ffebee;
color: #c62828;
}
</style>
</head>
<body>
<nav class="navbar">
<h2>لوحة الإدارة</h2>
<div>
<a href="dashboard.php" style="color: white;">لوحة التحكم</a>
<a href="logout.php" style="color: white; margin-right: 20px;">تسجيل الخروج</a>
</div>
</nav>
<div class="container">
<h1>إدارة المستخدمين</h1>
<p>إجمالي المستخدمين: <?php echo count($all_users); ?></p>
<table>
<thead>
<tr>
<th>المعرف</th>
<th>اسم المستخدم</th>
<th>البريد الإلكتروني</th>
<th>الاسم الكامل</th>
<th>الدور</th>
<th>الحالة</th>
</tr>
</thead>
<tbody>
<?php foreach ($all_users as $u): ?>
<tr>
<td><?php echo $u['id']; ?></td>
<td><?php echo htmlspecialchars($u['username']); ?></td>
<td><?php echo htmlspecialchars($u['email']); ?></td>
<td><?php echo htmlspecialchars($u['full_name']); ?></td>
<td>
<span class="role-badge role-<?php echo $u['role']; ?>">
<?php echo strtoupper($u['role']); ?>
</span>
</td>
<td><?php echo $u['is_active'] ? 'نشط' : 'غير نشط'; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</body>
</html>
تحذير أمني: تحقق دائماً من أذونات المستخدم على جانب الخادم. لا تعتمد فقط على إخفاء عناصر واجهة المستخدم - يمكن للمستخدمين التلاعب بالكود من جانب العميل. الفحوصات من جانب الخادم إلزامية.
نصيحة احترافية: قم بتخزين دور المستخدم في الجلسة بعد أول استرجاع لتجنب استعلامات قاعدة البيانات المتكررة. قم بتحديث دور الجلسة كلما تغير في قاعدة البيانات.
تمرين:
- أنشئ صفحة لوحة تحكم محمية باستخدام وسيط المصادقة
- أضف عمود الدور إلى جدول المستخدمين وحدث التسجيل لتعيين الدور الافتراضي
- أنشئ لوحة إدارة تعرض جميع المستخدمين (وصول للمسؤولين فقط)
- نفذ صفحة للمشرفين مع وظائف إدارية محدودة
- أضف شروط واجهة المستخدم القائمة على الأذونات لإظهار/إخفاء عناصر التنقل
- أنشئ نقاط نهاية API مع حماية قائمة على الأدوار
- نفذ سجل الوصول لتتبع من يصل إلى الصفحات المحمية
قائمة التحقق الأمنية الكاملة
- المصادقة - التحقق من هوية المستخدم باستخدام password_verify()
- التصريح - التحقق من أذونات المستخدم قبل السماح بالإجراءات
- أمان الجلسة - إعادة إنشاء المعرفات، التحقق من وكلاء المستخدم، تعيين المهلات
- التحقق من الإدخال - تنظيف والتحقق من جميع مدخلات المستخدم
- منع حقن SQL - استخدام العبارات المحضرة حصرياً
- منع XSS - تجاوز الإخراج باستخدام htmlspecialchars()
- حماية CSRF - تنفيذ رموز CSRF للنماذج
- أمان كلمة المرور - التشفير باستخدام PASSWORD_DEFAULT
- تقييد المعدل - منع القوة الغاشمة بتتبع محاولات تسجيل الدخول
- HTTPS فقط - كوكيز آمنة، فرض اتصالات SSL
الملخص
لقد قمت الآن ببناء نظام مصادقة وتصريح كامل! لقد تعلمت:
- إنشاء تسجيل مستخدم آمن مع التحقق وتشفير كلمة المرور
- تنفيذ أنظمة تسجيل الدخول مع إدارة الجلسات و"تذكرني"
- حماية الصفحات بوسيط المصادقة
- بناء أنظمة التحكم في الوصول القائمة على الأدوار
- تنفيذ التصريح القائم على الأذونات
- تأمين نقاط نهاية API بالتحقق من الأدوار
- اتباع أفضل الممارسات الأمنية