یک سایت جوملا تنها زمانی موفق است که امن باشد. اما امنیت در هاستهای اشتراکی ایرانی — با محدودیتهای دسترسی، عدم پشتیبانی از فایروالهای پیشرفته و قدیمیبودن برخی ماژولها — چالشی بزرگ محسوب میشود. در این مقاله، راهکارهایی عملی، تستشده و قابل اجرا ارائه میدهم که نهتنها سایت عمومی شما را محافظت میکند، بلکه برای پروژههای حساسی مانند سیستمهای آزمون آنلاین، فرمهای استخدام و پنلهای مدیریت داخلی نیز امنیت لازم را فراهم میکند — بدون نیاز به سرور اختصاصی یا دانش سیستمی پیشرفته.
گام ۱: تنظیمات امنیتی ضروری در configuration.php
این تنظیمات ساده، خط دفاعی اول شما هستند:
// جلوگیری از نمایش خطاهای سرور
public $error_reporting = 'none';
// مسیر جداگانه برای فایلهای لاگ (خارج از public_html)
public $log_path = '/home/youruser/logs';
// غیرفعال کردن امکان اجرای اسکریپتهای PHP در پوشههای بارگذاری
// (با افزونههای امنیتی — گام بعدی)
// تغییر پیشوند جداول برای سختتر کردن حملات
public $dbprefix = 'bal_'; // نه 'jos_'
گام ۲: فعالسازی و تنظیم افزونههای داخلی امنیتی
جوملا ۵ افزونههای امنیتی داخلی دارد که باید فعال شوند:
- System - Remember Me: غیرفعال کنید (در صورت عدم نیاز)
- Authentication - Joomla: تنها روش لاگین را از این طریق نگه دارید
- Content - Email Cloaking: فعال باشد تا اسپمرباتها ایمیلها را جمعآوری نکنند
همچنین، افزونهی Akeeba Admin Tools را نصب کنید — حتی در هاستهای اشتراکی، لایهای قوی از امنیت اضافه میکند.
گام ۳: جلوگیری از XSS و SQL Injection در کامپوننتهای سفارشی
در هر کامپوننتی که میسازید، این قوانین را رعایت کنید:
ورودیها را همیشه فیلتر کنید:
$input = \Joomla\CMS\Factory::getApplication()->input;
$id = $input->getInt('id', 0); // فقط عدد صحیح
$title = $input->getString('title', ''); // رشته — ولی بدون اسکریپت!
خروجیها را همیشه Escape کنید:
<?php echo htmlspecialchars($title, ENT_QUOTES, 'UTF-8'); ?>
در کوئریها از quoting استفاده کنید:
$db = \Joomla\CMS\Factory::getDbo();
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__mytable'))
->where($db->quoteName('id') . ' = ' . (int)$id);
گام ۴: ایجاد سیستم لاگین هوشمند با OTP (با استفاده از sms.ir یا api.ir)
برای پنلهای حساس (مثل سیستم آزمون)، لاگین دو مرحلهای ضروری است:
// در پلاگین سیستمی یا کامپوننت
$phone = $user->get('phone');
$code = rand(100000, 999999);
// ذخیرهی موقت کد در session
\Joomla\CMS\Factory::getApplication()->setUserState('otp.code', $code);
\Joomla\CMS\Factory::getApplication()->setUserState('otp.expires', time() + 300);
// ارسال با sms.ir
$url = 'https://api.sms.ir/v1/send';
$headers = [
'Content-Type: application/json',
'x-api-key: YOUR_SMS_IR_KEY'
];
$data = json_encode([
'mobile' => $phone,
'message' => "کد تأیید شما: {$code} — معتبر تا ۵ دقیقه"
]);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close($curl);
این روش، امنیت لاگین را حتی در صورت نشت رمز عبور، بهطور چشمگیری افزایش میدهد.
گام ۵: جلوگیری از تقلب در سیستمهای آزمون — تشخیص تغییر تب و کپیپیست
این ویژگیها را در صفحهی آزمون با JavaScript پیادهسازی کنید:
<script>
let tabSwitchCount = 0;
let copyAttempt = 0;
// تشخیص تغییر تب
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
tabSwitchCount++;
if (tabSwitchCount >= 2) {
alert('تغییر تب مجاز نیست. آزمون شما لغو خواهد شد.');
// ارسال درخواست به سرور برای ثبت تقلب
fetch('index.php?option=com_exam&task=logViolation', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ violation: 'tab_switch' })
}).then(() => window.location.href = '/exam/terminated');
}
}
});
// جلوگیری از کپیپیست
document.addEventListener('copy', function(e) {
copyAttempt++;
if (copyAttempt >= 1) {
e.preventDefault();
alert('کپی محتوا مجاز نیست.');
}
});
document.addEventListener('contextmenu', function(e) {
e.preventDefault(); // غیرفعال کردن راستکلیک
});
</script>
⚠️ نکته: این کدها را با یک اسکریپت مینیفایشده و رندومسازیشده در هر بار بارگذاری ارائه دهید تا دور زدن آن سختتر شود.
گام ۶: فعالسازی Content Security Policy (CSP) حتی در هاستهای اشتراکی
CSP میتواند اجرای اسکریپتهای مخرب را جلوگیری کند. در فایل .htaccess:
<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://api.sms.ir; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"
</IfModule>
اگر هاست شما از mod_headers پشتیبانی نمیکند، این هدر را در index.php اصلی جوملا اضافه کنید:
<?php
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';");
// سپس include پوشهی libraries را ادامه دهید
require_once 'libraries/bootstrap.php';
...
گام ۷: محدودیت دسترسی بر اساس IP یا نقش کاربری
برای پنلهای داخلی (مثل سیستم استخدام)، دسترسی را محدود کنید:
// در کنترلر کامپوننت
$user = \Joomla\CMS\Factory::getUser();
$allowedGroups = [8, 9]; // ID گروههای مجاز
if (!in_array($user->id, $allowedGroups)) {
\Joomla\CMS\Factory::getApplication()->enqueueMessage('دسترسی غیرمجاز', 'error');
\Joomla\CMS\Factory::getApplication()->redirect('index.php');
}
تجربهی شخصی: سیستم آزمون امن برای یک مرکز آموزشی در سیرجان
در یکی از پروژههای اخیر، سیستم آزمونی طراحی کردم که:
- لاگین با OTP از طریق sms.ir
- تشخیص تغییر تب و محدودیت کپی
- ذخیرهسازی فعالیتهای کاربر بهصورت زنده
- گزارش تخلفات به ادمین با ایمیل و پیامک
این سیستم در یک هاست اشتراکی ایرانی راهاندازی شد و در طول یک سال، هیچ مورد تقلبی گزارش نشد — حتی با وجود هزاران شرکتکننده.
جمعبندی
امنیت در جوملا ۵ یک ویژگی نیست؛ یک فرآیند است. با رعایت اصول سادهای که در این مقاله گفته شد — از تنظیمات پایه گرفته تا جلوگیری از تقلب در آزمونها — میتوانید سایتی بسازید که نهتنها زیبا و کاربردی است، بلکه سپری در برابر تهدیدات دنیای دیجیتال نیز هست.
یادتان باشد: امنیت، احترام به کاربر است. چون دادههایش را گران میدانید.
