📖 درس پنجم: امنیت API پیشرفته
🎯 هدف این درس: آشنایی با OWASP Top 10 برای API، پیادهسازی لایههای امنیتی پیشرفته شامل جلوگیری از SQL Injection، XSS، CSRF، Rate Limiting، امنیت Headers و بهترین شیوههای امنیتی در API.
مهمان عزیز! 👋
در درس قبل، یک سیستم احراز هویت کامل با JWT پیادهسازی کردیم. اما امنیت فقط به احراز هویت محدود نمیشود. APIهای مدرن با تهدیدات متنوعی روبرو هستند و یک توسعهدهنده حرفهای باید تمام لایههای امنیتی را بشناسد و پیادهسازی کند.
در این درس، با مهمترین تهدیدات امنیتی در APIها آشنا میشویم و راهکارهای عملی برای مقابله با هرکدام را پیادهسازی میکنیم.
💡 OWASP چیست؟
OWASP (Open Web Application Security Project) یک سازمان غیرانتفاعی است که لیستی از ۱۰ تهدید برتر امنیتی وب را منتشر میکند. این لیست به عنوان استاندارد طلایی امنیت وب شناخته میشود و هر توسعهدهندهای باید با آن آشنا باشد.
🛡️ OWASP Top 10 برای API
مهمترین تهدیدات امنیتی برای APIها عبارتند از:
| ردیف | تهدید | توضیح |
|---|---|---|
| ۱ | Broken Object Level Authorization | دسترسی به اشیایی که کاربر مجوز ندارد |
| ۲ | Broken Authentication | ضعف در سیستم احراز هویت |
| ۳ | Excessive Data Exposure | بازگرداندن دادههای اضافی به کلاینت |
| ۴ | Lack of Resources & Rate Limiting | عدم محدودیت در تعداد درخواستها |
| ۵ | Broken Function Level Authorization | دسترسی به توابعی که کاربر مجوز ندارد |
| ۶ | Mass Assignment | تغییر فیلدهای غیرمجاز در بدنه درخواست |
| ۷ | Security Misconfiguration | تنظیمات امنیتی نامناسب |
| ۸ | Injection | تزریق کد مخرب (SQLi, NoSQLi, OS Command) |
| ۹ | Improper Assets Management | مدیریت ضعیف نسخههای API |
| ۱۰ | Insufficient Logging & Monitoring | لاگگیری و نظارت ناکافی |
🛡️ جلوگیری از SQL Injection
SQL Injection یکی از خطرناکترین حملات است که در آن مهاجم کد SQL مخرب را از طریق ورودیهای کاربر به دیتابیس تزریق میکند.
❌ مثال کد آسیبپذیر:
$query = "SELECT * FROM users WHERE id = " . $_GET['id'];
اگر مهاجم id=1 OR 1=1 را ارسال کند، تمام کاربران نمایش داده میشوند!
SQL Injection Protection
PHP
8.2
<?php
// ✅ راهحل صحیح: استفاده از Prepared Statements
// روش ۱: با PDO (توصیه شده)
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute([':id' => $_GET['id']]);
$users = $stmt->fetchAll();
// روش ۲: با mysqli
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $_GET['id']);
$stmt->execute();
$result = $stmt->get_result();
// 💡 قانون طلایی: هرگز دادههای کاربر را مستقیماً در SQL وارد نکن!
🛡️ جلوگیری از XSS (Cross-Site Scripting)
XSS حملهای است که در آن مهاجم اسکریپتهای مخرب را به صفحات وب تزریق میکند. در APIها، معمولاً این حمله از طریق دادههای ورودی که در پاسخ بازگردانده میشوند، اتفاق میافتد.
XSS Protection
PHP
8.2
<?php
// ❌ آسیبپذیر: بازگرداندن مستقیم دادههای ورودی
// $data = $_POST['comment'];
// return Response::success(['comment' => $data]);
// ✅ راهحل صحیح: Sanitize کردن دادهها
class Security
{
// ۱. استفاده از htmlspecialchars برای Escape کردن
public static function escape($input)
{
if (is_array($input)) {
return array_map([self, 'escape'], $input);
}
return htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
}
// ۲. حذف تگهای HTML (برای ورودیهایی که نباید HTML داشته باشند)
public static function stripTags($input)
{
if (is_array($input)) {
return array_map([self, 'stripTags'], $input);
}
return strip_tags($input);
}
// ۳. فیلتر کردن با filter_var
public static function sanitize($input, $type = 'string')
{
switch ($type) {
case 'email':
return filter_var($input, FILTER_SANITIZE_EMAIL);
case 'int':
return filter_var($input, FILTER_SANITIZE_NUMBER_INT);
case 'url':
return filter_var($input, FILTER_SANITIZE_URL);
default:
return filter_var($input, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH);
}
}
}
// استفاده در کنترلر
$data = $request->getBody();
$sanitizedData = Security::escape($data);
🛡️ جلوگیری از CSRF (Cross-Site Request Forgery)
CSRF حملهای است که در آن مهاجم کاربر را فریب میدهد تا درخواستهای ناخواستهای به سرور ارسال کند. در APIهای مبتنی بر توکن، این حمله کمتر رخ میدهد، اما همچنان باید اقدامات پیشگیرانه انجام داد.
CSRF Protection
PHP
8.2
<?php
// روشهای جلوگیری از CSRF در API
// ۱. استفاده از توکن در Header (مخصوص API)
// درخواست باید شامل Header زیر باشد:
// X-CSRF-Token: {token}
class CSRF
{
public static function generateToken()
{
return bin2hex(random_bytes(32));
}
public static function validateToken($token)
{
// توکن را با مقدار ذخیرهشده در Session یا Cache مقایسه کن
$storedToken = $_SESSION['csrf_token'] ?? null;
if (empty($storedToken) || !hash_equals($storedToken, $token)) {
return false;
}
return true;
}
}
// ۲. بررسی Origin و Referer (لایه اضافی)
public static function validateOrigin()
{
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
$referer = $_SERVER['HTTP_REFERER'] ?? '';
$allowedOrigins = ['https://rajestary.com', 'https://api.rajestary.com'];
foreach ($allowedOrigins as $allowed) {
if (strpos($origin, $allowed) !== false ||
strpos($referer, $allowed) !== false) {
return true;
}
}
return false;
}
🛡️ Rate Limiting (محدودیت نرخ درخواست)
Rate Limiting از حملات Brute Force و DDoS جلوگیری میکند و باعث میشود API شما پایدارتر بماند.
RateLimiter.php
PHP
8.2
<?php
class RateLimiter
{
private $key;
private $maxRequests;
private $timeWindow; // بر حسب ثانیه
public function __construct($maxRequests = 60, $timeWindow = 60)
{
$this->key = 'rate_limit_' . $_SERVER['REMOTE_ADDR'];
$this->maxRequests = $maxRequests;
$this->timeWindow = $timeWindow;
}
// بررسی و محدود کردن درخواستها
public function check()
{
// در این مثال از فایل برای ذخیره استفاده میکنیم
// در محیط تولید از Redis یا Memcached استفاده کن
$filePath = __DIR__ . '/../storage/rate_limit/' . $this->key . '.json';
if (file_exists($filePath)) {
$data = json_decode(file_get_contents($filePath), true);
// بررسی پنجره زمانی
if (time() - $data['window_start'] < $this->timeWindow) {
if ($data['count'] >= $this->maxRequests) {
return false; // محدودیت اعمال شد
}
// افزایش شمارنده
$data['count']++;
} else {
// پنجره جدید
$data = [
'count' => 1,
'window_start' => time()
];
}
} else {
$data = [
'count' => 1,
'window_start' => time()
];
}
// ذخیره دادهها
file_put_contents($filePath, json_encode($data));
return true;
}
// دریافت هدرهای Rate Limit
public function getHeaders()
{
$filePath = __DIR__ . '/../storage/rate_limit/' . $this->key . '.json';
if (file_exists($filePath)) {
$data = json_decode(file_get_contents($filePath), true);
return [
'X-RateLimit-Limit' => $this->maxRequests,
'X-RateLimit-Remaining' => $this->maxRequests - $data['count'],
'X-RateLimit-Reset' => $data['window_start'] + $this->timeWindow
];
}
return [
'X-RateLimit-Limit' => $this->maxRequests,
'X-RateLimit-Remaining' => $this->maxRequests,
'X-RateLimit-Reset' => time() + $this->timeWindow
];
}
}
// استفاده در Middleware
public static function rateLimit()
{
$limiter = new RateLimiter(100, 60); // ۱۰۰ درخواست در ۶۰ ثانیه
if (!$limiter->check()) {
http_response_code(429);
echo json_encode([
'status' => 'error',
'message' => 'Too many requests. Please try again later.'
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
exit;
}
// افزودن هدرهای Rate Limit به پاسخ
$headers = $limiter->getHeaders();
foreach ($headers as $key => $value) {
header($key . ': ' . $value);
}
}
🛡️ امنیت Headers
هدرهای HTTP امنیتی از حملات مختلف جلوگیری میکنند. این هدرها باید در تمام پاسخهای API ارسال شوند.
Security Headers
PHP
8.2
<?php
// کلاس مدیریت هدرهای امنیتی
class SecurityHeaders
{
public static function apply()
{
// ۱. جلوگیری از Clickjacking
header('X-Frame-Options: DENY');
// ۲. جلوگیری از MIME Sniffing
header('X-Content-Type-Options: nosniff');
// ۳. فعالسازی XSS Protection
header('X-XSS-Protection: 1; mode=block');
// ۴. Content Security Policy (CSP)
header("Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;");
// ۵. HSTS - اجباری کردن HTTPS
header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
// ۶. Reference Policy - کنترل ارسال Referer
header('Referrer-Policy: strict-origin-when-cross-origin');
// ۷. حذف Server header (اطلاعات سرور را پنهان کن)
header_remove('Server');
// ۸. Permissions Policy - محدود کردن قابلیتهای مرورگر
header("Permissions-Policy: geolocation=(), microphone=(), camera=(), payment=()");
}
}
// فراخوانی در Bootstrap (index.php)
SecurityHeaders::apply();
💡 CSP چیست و چرا مهم است؟
CSP (Content Security Policy) یک لایه امنیتی اضافی است که به جلوگیری از حملات XSS کمک میکند. با CSP مشخص میکنی که مرورگر فقط محتوای خاصی (مثل اسکریپتها، استایلها و تصاویر) از منابع معتبر را بارگذاری کند.
🛡️ Input Validation و Sanitization
اعتبارسنجی ورودی (Validation) و پاکسازی (Sanitization) دو اصل مهم در امنیت API هستند. Validation بررسی میکند که دادهها با قوانین مشخص مطابقت دارند و Sanitization دادهها را از محتوای مخرب پاک میکند.
Input Validation
PHP
8.2
<?php
class InputValidator
{
public static function validateEmail($email)
{
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
public static function validateUrl($url)
{
return filter_var($url, FILTER_VALIDATE_URL) !== false;
}
public static function validateInteger($value, $min = null, $max = null)
{
$options = [];
if ($min !== null) $options['min_range'] = $min;
if ($max !== null) $options['max_range'] = $max;
return filter_var($value, FILTER_VALIDATE_INT, ['options' => $options]) !== false;
}
public static function validateString($value, $minLength = null, $maxLength = null)
{
$length = mb_strlen($value);
if ($minLength !== null && $length < $minLength) {
return false;
}
if ($maxLength !== null && $length > $maxLength) {
return false;
}
return true;
}
// اعتبارسنجی کامل یک آرایه از دادهها
public static function validate($data, $rules)
{
$errors = [];
foreach ($rules as $field => $fieldRules) {
$value = $data[$field] ?? null;
$rulesList = explode('|', $fieldRules);
foreach ($rulesList as $rule) {
if ($rule === 'required' && empty($value)) {
$errors[$field][] = "The {$field} field is required";
}
if ($rule === 'email' && !self::validateEmail($value)) {
$errors[$field][] = "The {$field} must be a valid email";
}
if (strpos($rule, 'min:') === 0) {
$min = explode(':', $rule)[1];
if (mb_strlen($value) < $min) {
$errors[$field][] = "The {$field} must be at least {$min} characters";
}
}
}
}
return empty($errors) ? true : $errors;
}
}
// استفاده در کنترلر
$data = $request->getBody();
$validation = InputValidator::validate($data, [
'name' => 'required|min:3',
'email' => 'required|email',
'age' => 'integer'
]);
if ($validation !== true) {
return Response::error('Validation failed', 422, $validation);
}
🛡️ لاگگیری امنیتی (Security Logging)
لاگگیری مناسب به شما کمک میکند حملات را شناسایی و بررسی کنید.
SecurityLogger.php
PHP
8.2
<?php
class SecurityLogger
{
private static $logPath = '/var/log/security.log';
public static function log($event, $details = [])
{
$logEntry = [
'timestamp' => date('Y-m-d H:i:s'),
'event' => $event,
'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
'method' => $_SERVER['REQUEST_METHOD'] ?? 'unknown',
'uri' => $_SERVER['REQUEST_URI'] ?? 'unknown',
'details' => $details
];
$logLine = json_encode($logEntry) . PHP_EOL;
// نوشتن در فایل لاگ (با permission مناسب)
file_put_contents(self::$logPath, $logLine, FILE_APPEND | LOCK_EX);
}
// لاگ رویدادهای امنیتی خاص
public static function logFailedLogin($email)
{
self::log('LOGIN_FAILED', ['email' => $email]);
}
public static function logSuspiciousActivity($description)
{
self::log('SUSPICIOUS_ACTIVITY', ['description' => $description]);
}
public static function logRateLimitExceeded($limit)
{
self::log('RATE_LIMIT_EXCEEDED', ['limit' => $limit]);
}
public static function logUnauthorizedAccess($endpoint)
{
self::log('UNAUTHORIZED_ACCESS', ['endpoint' => $endpoint]);
}
// خواندن و تحلیل لاگها (فقط برای مدیران)
public static function getLogs($limit = 100)
{
if (!file_exists(self::$logPath)) {
return [];
}
$logs = file(self::$logPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$logs = array_reverse($logs); // جدیدترینها اول
$logs = array_slice($logs, 0, $limit);
return array_map('json_decode', $logs);
}
}
🔴 خطاهای رایج در امنیت API
- ❌ اشتباه: بازگرداندن خطاهای کامل دیتابیس به کاربر.
- ✅ درست: خطاها را لاگ کن و پیامهای عمومی برگردان.
- ❌ اشتباه: نداشتن Rate Limiting.
- ✅ درست: همیشه محدودیت نرخ درخواست داشته باش.
- ❌ اشتباه: استفاده از الگوریتمهای ضعیف هش.
- ✅ درست: از
password_hash()باPASSWORD_DEFAULTاستفاده کن.
- ❌ اشتباه: عدم بررسی دسترسیها در سطح شیء.
- ✅ درست: همیشه بررسی کن کاربر به شیء مورد نظر دسترسی دارد.
💎 نکات کلیدی درس
- ✅ OWASP Top 10 مرجع اصلی امنیت API است.
- ✅ برای جلوگیری از SQL Injection از Prepared Statements استفاده کن.
- ✅ برای جلوگیری از XSS از
htmlspecialchars()و Sanitization استفاده کن. - ✅ Rate Limiting از حملات Brute Force و DDoS جلوگیری میکند.
- ✅ هدرهای امنیتی مثل CSP، HSTS و X-Frame-Options ضروری هستند.
- ✅ Input Validation و Sanitization دو اصل مهم در امنیت هستند.
- ✅ لاگگیری امنیتی به تشخیص و بررسی حملات کمک میکند.
- ✅ هرگز به کاربر اطلاعات داخلی سرور را نشان نده.
🛠️ پروژه عملی درس پنجم
مهمان عزیز، حالا یک لایه امنیتی کامل به API خود اضافه کن!
مسئله:
یک سیستم امنیتی کامل برای API محصولات پیادهسازی کن:
- ✅ Rate Limiting با محدودیت ۵۰ درخواست در دقیقه برای هر کاربر.
- ✅ Input Validation برای تمام Endpointهای محصولات.
- ✅ Sanitization دادههای ورودی.
- ✅ هدرهای امنیتی (CSP، HSTS، X-Frame-Options).
- ✅ لاگگیری امنیتی برای رویدادهای مهم.
- ✅ بررسی دسترسی به اشیاء (Object Level Authorization).
🧪 راهحل پروژه (پاسخ)
مراحل پیادهسازی:
- 1️⃣ کلاس
RateLimiterرا برای محدودیت نرخ درخواست ایجاد کن. - 2️⃣ کلاس
SecurityHeadersرا برای افزودن هدرهای امنیتی بساز. - 3️⃣ کلاس
InputValidatorرا با قوانین اعتبارسنجی کامل پیادهسازی کن. - 4️⃣ کلاس
SecurityLoggerرا برای لاگگیری رویدادها ایجاد کن. - 5️⃣ در هر کنترلر، Validation و Sanitization را اعمال کن.
- 6️⃣ در Bootstrap، هدرهای امنیتی و Rate Limiting را اضافه کن.
📝 تمرینهای عملی
🧪 تمرین ۱ (ساده):
Rate Limiting را روی API کاربران پیادهسازی کن. سپس با ارسال درخواستهای متعدد، پاسخ ۴۲۹ را دریافت کن.
🧪 تمرین ۲ (متوسط):
Input Validation کامل برای ثبتنام کاربر پیادهسازی کن. قوانین شامل: نام (حداقل ۳ کاراکتر، فقط حروف فارسی)، ایمیل (معتبر)، رمز عبور (حداقل ۸ کاراکتر، شامل عدد و حرف بزرگ) و تلفن همراه (شماره ایرانی) باشد.
🧪 تمرین ۳ (چالشی):
یک سیستم شناسایی حملات Brute Force پیادهسازی کن. اگر کاربری بیش از ۵ بار با ایمیل اشتباه وارد شود، IP او را به مدت ۱۵ دقیقه مسدود کن. از Redis یا فایل برای ذخیره اطلاعات استفاده کن.
🏁 جمعبندی درس
مهمان عزیز، در این درس یاد گرفتی:
- ✅ OWASP Top 10 و مهمترین تهدیدات امنیتی API.
- ✅ چگونه از SQL Injection با Prepared Statements جلوگیری کنی.
- ✅ چگونه از XSS با Sanitization و Escape کردن جلوگیری کنی.
- ✅ Rate Limiting و اهمیت آن در امنیت API.
- ✅ هدرهای امنیتی و نحوه پیادهسازی آنها.
- ✅ Input Validation و Sanitization برای دادههای ورودی.
- ✅ لاگگیری امنیتی و اهمیت آن در تشخیص حملات.
حالا API شما یک لایه امنیتی کامل دارد و در برابر حملات رایج مقاوم شده است. در درس بعدی، مستندسازی API با OpenAPI (Swagger) را یاد میگیریم. آمادهای؟ 🚀
🗺️ نقشه راه دوره: شما اینجا هستید!
برای اینکه بدانی دقیقاً کجای مسیر هستی و چه درسهایی در انتظار توست، به جدول زیر نگاه کن. درس فعلی با رنگ متفاوت مشخص شده است.
| درس | عنوان درس | آنچه یاد میگیرید |
|---|---|---|
| ۱ | مفاهیم پایه API | HTTP، REST، معماری Client-Server |
| ۲ | پیادهسازی RESTful API با PHP خام | مسیریابی، متدها، پارامترها، پاسخهای JSON |
| ۳ | مدیریت دادهها و پایگاهداده | اتصال PDO، CRUD، تراکنشها، Pagination |
| ۴ | اعتبارسنجی و احراز هویت | JWT، Roles/Permissions، Middleware |
| ۵ | امنیت API پیشرفته | OWASP Top 10، SQLi، XSS، CSRF، Rate Limiting |
| ۶ | مستندسازی API با OpenAPI | Swagger، OpenAPI Specification، مستندات تعاملی |
| ۷ | Caching و افزایش عملکرد | Redis، ETag، Cache-Control، Query Optimization |
| ۸ | API Versioning و مدیریت چرخه حیات | استراتژیهای نسخهبندی، Deprecation، Backward Compatibility |
| ۹ | تست و دیباگ API حرفهای | PHPUnit، Mocking، Logging، Postman Collection |
| ۱۰ | پروژه نهایی: API فروشگاهی | پروژه کامل فروشگاه اینترنتی با تمام قابلیتها |




نظر خود را بنویسید
با ثبت نظر، به بهبود محتوای ما کمک کنید