🔒 فصل ۱۳: امنیت و عملکرد وردپرس
وردپرس بهخاطر محبوبیتش، هدف اصلی هکرهاست. توی این فصل یاد میگیریم چطور سایت رو امن کنیم و سرعتش رو چند برابر کنیم - دو ستون موفقیت هر سایت حرفهای.
وردپرس بهخاطر محبوبیتش، هدف اصلی هکرهاست. توی این فصل یاد میگیریم چطور سایت رو امن کنیم و سرعتش رو چند برابر کنیم – دو ستون موفقیت هر سایت حرفهای.
🛡 اصول طلایی امنیت
هر ورودی کاربر نامعتبره تا اعتبارسنجی نشه. هر خروجی باید escape بشه. هر اقدام مهم نیاز به nonce داره. هرگز SQL injection رو نادیده نگیر.
چکلیست امنیت اولیه
- هیچوقت کاربری به نام
adminنداشته باش - رمز عبور قوی (۱۶+ کاراکتر) با اعداد، حروف بزرگ/کوچک و نماد
- احراز دو مرحلهای (2FA) فعال باشه
- HTTPS اجباری باشه (با Let’s Encrypt رایگان)
- وردپرس و افزونهها همیشه بهروز
- پشتیبانگیری روزانه به فضای خارج از سرور
- محدودیت تلاش ورود (Limit Login Attempts)
- فایروال (Wordfence یا iThemes Security)
- اسکن ماهانه بدافزار
- پیشوند جدول از
wp_تغییر کرده باشه
🧹 پاکسازی (Sanitize) و خروجی امن (Escape)
یه قانون ساده: Sanitize on input, Escape on output. هر داده که وارد سیستم میشه باید پاکسازی بشه، و هر داده که نمایش داده میشه باید escape بشه.
توابع پاکسازی (sanitize_*)
// متن ساده (یه خطی)
$name = sanitize_text_field( $_POST['name'] );
// ایمیل
$email = sanitize_email( $_POST['email'] );
// متن چندخطی
$bio = sanitize_textarea_field( $_POST['bio'] );
// URL برای ذخیره در DB
$website = esc_url_raw( $_POST['website'] );
// عدد صحیح مثبت
$count = absint( $_POST['count'] );
// عدد صحیح (میتونه منفی باشه)
$value = intval( $_POST['value'] );
// عدد اعشاری
$price = floatval( $_POST['price'] );
// HTML امن (با تگهای مجاز)
$content = wp_kses_post( $_POST['content'] );
// HTML با تگهای دلخواه
$html = wp_kses( $_POST['html'], array(
'a' => array( 'href' => array(), 'title' => array() ),
'br' => array(),
'em' => array(),
'strong' => array(),
) );
// Slug (نام انگلیسی URL-friendly)
$slug = sanitize_title( $_POST['slug'] );
// Key (فقط حروف، عدد، خط تیره و آندرلاین)
$key = sanitize_key( $_POST['key'] );
// نام فایل
$filename = sanitize_file_name( $_POST['file'] );
// رنگ هگز
$color = sanitize_hex_color( $_POST['color'] );
// شماره تلفن
$phone = preg_replace( '/[^0-9+]/', '', $_POST['phone'] );
توابع Escape (esc_*)
// در HTML معمولی
echo esc_html( $title );
// در attribute
echo '<input value="' . esc_attr( $value ) . '">';
// در href یا src
echo '<a href="' . esc_url( $link ) . '">Click</a>';
// در textarea
echo '<textarea>' . esc_textarea( $content ) . '</textarea>';
// در JavaScript
echo '<script>var name = "' . esc_js( $name ) . '";</script>';
// HTML با تگهای مجاز
echo wp_kses_post( $rich_content );
// با ترجمه
echo esc_html__( 'Hello', 'textdomain' ); // ترجمه + escape
esc_html_e( 'Hello', 'textdomain' ); // مستقیم چاپ
هرگز echo $variable بدون escape ننویس. حتی اگه فکر میکنی متغیر امنه، احتمال داره از منبع غیرامن اومده باشه.
SQL injection – استفاده از prepare
global $wpdb;
// ❌ آسیبپذیر
$results = $wpdb->get_results(
"SELECT * FROM {$wpdb->prefix}orders WHERE user_id = $user_id"
);
// ✅ امن
$results = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}orders WHERE user_id = %d AND status = %s",
$user_id,
$status
) );
// placeholder ها:
// %d = integer
// %f = float
// %s = string
// IN clause با تعداد متغیر
$ids = array( 1, 2, 3, 4 );
$placeholders = implode( ', ', array_fill( 0, count( $ids ), '%d' ) );
$query = $wpdb->prepare(
"SELECT * FROM table WHERE id IN ($placeholders)",
...$ids
);
🎫 Nonces – جلوگیری از CSRF
CSRF (Cross-Site Request Forgery) یعنی کسی از طرف کاربر بدون اطلاعش درخواست بفرسته. nonce یه توکن یکبار مصرفه که این حمله رو خنثی میکنه.
در فرم
<form method="post">
<?php wp_nonce_field( 'save_settings', '_settings_nonce' ); ?>
<input type="text" name="my_field">
<input type="submit">
</form>
در پردازش
// روش ۱: اگه نباشه die میکنه
check_admin_referer( 'save_settings', '_settings_nonce' );
// روش ۲: دستی چک کن
if ( ! isset( $_POST['_settings_nonce'] ) ||
! wp_verify_nonce( $_POST['_settings_nonce'], 'save_settings' ) ) {
wp_die( 'درخواست نامعتبر' );
}
// در AJAX
check_ajax_referer( 'my_ajax_action', 'security' );
در URL
// ساخت URL با nonce
$url = wp_nonce_url(
admin_url( 'admin.php?action=delete&id=123' ),
'delete_item_123'
);
// در پردازش
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'delete_item_123' ) ) {
wp_die( 'دسترسی غیرمجاز' );
}
🔐 امنسازی wp-config.php
// ۱. کلیدهای امنیتی - از https://api.wordpress.org/secret-key/1.1/salt/
define( 'AUTH_KEY', 'long-random-string-here' );
define( 'SECURE_AUTH_KEY', 'long-random-string-here' );
define( 'LOGGED_IN_KEY', 'long-random-string-here' );
define( 'NONCE_KEY', 'long-random-string-here' );
define( 'AUTH_SALT', 'long-random-string-here' );
define( 'SECURE_AUTH_SALT', 'long-random-string-here' );
define( 'LOGGED_IN_SALT', 'long-random-string-here' );
define( 'NONCE_SALT', 'long-random-string-here' );
// ۲. غیرفعال کردن ویرایش فایل از پنل
define( 'DISALLOW_FILE_EDIT', true );
// ۳. غیرفعال کردن نصب/حذف افزونه از پنل (سایتهای پروداکشن)
define( 'DISALLOW_FILE_MODS', true );
// ۴. اجبار HTTPS برای ادمین
define( 'FORCE_SSL_ADMIN', true );
// ۵. آپدیت خودکار هسته (فقط minor)
define( 'WP_AUTO_UPDATE_CORE', 'minor' );
// ۶. مخفی کردن خطاهای PHP در پروداکشن
define( 'WP_DEBUG', false );
define( 'WP_DEBUG_DISPLAY', false );
define( 'WP_DEBUG_LOG', true );
// ۷. افزایش حافظه PHP
define( 'WP_MEMORY_LIMIT', '256M' );
// ۸. محدود کردن نسخههای Revision
define( 'WP_POST_REVISIONS', 5 );
// ۹. کاهش بازه auto-save
define( 'AUTOSAVE_INTERVAL', 300 ); // ۵ دقیقه
// ۱۰. پاکسازی Trash
define( 'EMPTY_TRASH_DAYS', 7 );
محافظت از wp-config.php با .htaccess
# محافظت از wp-config.php
<Files wp-config.php>
order allow,deny
deny from all
</Files>
# محافظت از .htaccess خودش
<Files .htaccess>
order allow,deny
deny from all
</Files>
# جلوگیری از نمایش دایرکتوری
Options -Indexes
# جلوگیری از ورود به wp-includes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>
# محافظت از xmlrpc.php (اگه استفاده نمیکنی)
<Files xmlrpc.php>
order deny,allow
deny from all
</Files>
📡 Security Headers
هدرهای HTTP که امنیت رو در سطح مرورگر افزایش میدن:
<IfModule mod_headers.c>
# جلوگیری از Clickjacking
Header set X-Frame-Options "SAMEORIGIN"
# جلوگیری از MIME-sniffing
Header set X-Content-Type-Options "nosniff"
# XSS Protection (مرورگرهای قدیمی)
Header set X-XSS-Protection "1; mode=block"
# Referrer Policy
Header set Referrer-Policy "strict-origin-when-cross-origin"
# HSTS - اجبار HTTPS
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# Content Security Policy
Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:;"
# Permissions Policy
Header set Permissions-Policy "geolocation=(), microphone=(), camera=()"
# حذف هدر اطلاعات سرور
Header unset X-Powered-By
Header unset Server
</IfModule>
بعد از اعمال، با securityheaders.com امتیاز سایتت رو چک کن. هدف A یا A+!
⚡ سیستم کش
کش یعنی نگه داشتن خروجی محاسبهشده تا دفعه بعد سریعتر تحویل داده بشه. سرعت سایت رو ۲ تا ۱۰ برابر میکنه.
انواع کش
| نوع کش | چی رو کش میکنه؟ | ابزار |
|---|---|---|
| Page Cache | HTML کامل صفحه | WP Rocket, W3 Total Cache |
| Object Cache | نتایج کوئری دیتابیس | Redis, Memcached |
| Browser Cache | CSS, JS, تصاویر در مرورگر | هدرهای HTTP |
| OPcache | کد کامپایلشده PHP | پیشفرض PHP 7+ |
| CDN Cache | محتوای استاتیک نزدیک کاربر | Cloudflare, ArvanCloud |
Browser Cache در .htaccess
<IfModule mod_expires.c>
ExpiresActive On
# تصاویر - یک سال
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
# CSS و JS - یک ماه
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
# فونت - یک سال
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
# HTML - بدون کش
ExpiresByType text/html "access plus 0 seconds"
</IfModule>
# GZIP فشردهسازی
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript application/json
</IfModule>
⏱ Transients API
سادهترین راه برای کش کردن داده در وردپرس. مثل Cache.set() در زبانهای دیگه.
// ذخیره با مدت زمان
set_transient( 'my_data', $data, HOUR_IN_SECONDS );
// مدتها:
// MINUTE_IN_SECONDS = 60
// HOUR_IN_SECONDS = 3600
// DAY_IN_SECONDS = 86400
// WEEK_IN_SECONDS = 604800
// MONTH_IN_SECONDS = 2592000
// YEAR_IN_SECONDS = 31536000
// خوندن
$data = get_transient( 'my_data' );
if ( false === $data ) {
// محاسبه دوباره و ذخیره
$data = expensive_calculation();
set_transient( 'my_data', $data, HOUR_IN_SECONDS );
}
// حذف
delete_transient( 'my_data' );
مثال واقعی – کش کردن آمار سایت
function get_site_stats() {
$stats = get_transient( 'site_stats' );
if ( false === $stats ) {
// کوئریهای سنگین
$stats = array(
'posts' => wp_count_posts()->publish,
'comments' => wp_count_comments()->approved,
'users' => count_users()['total_users'],
'products' => wp_count_posts( 'product' )->publish,
);
// ۶ ساعت کش
set_transient( 'site_stats', $stats, 6 * HOUR_IN_SECONDS );
}
return $stats;
}
// پاک کردن کش وقتی نوشته جدید منتشر شد
add_action( 'publish_post', function() {
delete_transient( 'site_stats' );
} );
توی WooCommerce Advanced Reports که خودت ساختی، استفاده از Transients میتونه گزارشهای سنگین رو ۱۰ برابر سریعتر کنه. مخصوصاً برای محاسبات روزانه/ماهانه.
🚀 بهینهسازی پیشرفته
۱. غیرفعال کردن قابلیتهای اضافی
// حذف emoji
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
// حذف فید RSS اضافی
remove_action( 'wp_head', 'feed_links_extra', 3 );
// حذف لینکهای مدیریت ویندوز
remove_action( 'wp_head', 'wlwmanifest_link' );
remove_action( 'wp_head', 'rsd_link' );
// حذف نسخه وردپرس
remove_action( 'wp_head', 'wp_generator' );
// حذف لینکهای REST API و oEmbed (اگه نیاز نداری)
remove_action( 'wp_head', 'rest_output_link_wp_head', 10 );
remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );
// غیرفعال کردن XML-RPC
add_filter( 'xmlrpc_enabled', '__return_false' );
// غیرفعال کردن Heartbeat در فرانت
add_action( 'init', function() {
if ( ! is_admin() ) {
wp_deregister_script( 'heartbeat' );
}
} );
// کاهش فرکانس Heartbeat در ادمین
add_filter( 'heartbeat_settings', function( $settings ) {
$settings['interval'] = 60; // به جای ۱۵ ثانیه
return $settings;
} );
۲. بهینهسازی دیتابیس
// پاک کردن revision های قدیمی (اجرا در phpMyAdmin)
DELETE FROM wp_posts WHERE post_type = 'revision';
// پاک کردن نوشتههای Trash
DELETE FROM wp_posts WHERE post_status = 'trash';
// پاک کردن دیدگاههای اسپم
DELETE FROM wp_comments WHERE comment_approved = 'spam';
// پاک کردن metadata یتیم
DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts wp ON wp.ID = pm.post_id
WHERE wp.ID IS NULL;
// پاک کردن transient های منقضی
DELETE FROM wp_options
WHERE option_name LIKE '_transient_timeout_%'
AND option_value < UNIX_TIMESTAMP();
// بهینهسازی جدولها
OPTIMIZE TABLE wp_posts, wp_postmeta, wp_options, wp_comments;
۳. بهینهسازی تصاویر
- WebP و AVIF: فرمتهای مدرن با حجم ۳۰-۵۰٪ کمتر از JPG
- Lazy Loading: از وردپرس ۵.۵ به بعد بهصورت پیشفرض
- اندازه مناسب: از
srcsetاستفاده کن - افزونهها: ShortPixel, Smush, EWWW Image Optimizer
۴. حذف اسکریپتهای اضافی از صفحات خاص
// حذف ووکامرس از صفحاتی که نیاز نداره
add_action( 'wp_enqueue_scripts', function() {
if ( ! is_woocommerce() && ! is_cart() && ! is_checkout() ) {
wp_dequeue_style( 'woocommerce-general' );
wp_dequeue_style( 'woocommerce-layout' );
wp_dequeue_style( 'woocommerce-smallscreen' );
wp_dequeue_script( 'wc-cart-fragments' );
}
}, 99 );
// حذف Contact Form 7 از همه صفحات بهجز برگه تماس
add_action( 'wp_enqueue_scripts', function() {
if ( ! is_page( 'contact' ) ) {
wp_dequeue_script( 'contact-form-7' );
wp_dequeue_style( 'contact-form-7' );
}
}, 99 );
۵. ابزارهای اندازهگیری
- Google PageSpeed Insights – رسمی و معتبر
- GTmetrix – تحلیل عمیق
- WebPageTest – حرفهای
- Query Monitor – افزونه برای بررسی کوئریهای کند
اهداف عملکرد
- زمان لود اولیه: کمتر از ۲ ثانیه
- LCP (Largest Contentful Paint): کمتر از ۲.۵ ثانیه
- CLS (Cumulative Layout Shift): کمتر از ۰.۱
- INP (Interaction to Next Paint): کمتر از ۲۰۰ms
- تعداد درخواستها: کمتر از ۵۰
- حجم کل صفحه: کمتر از ۲ مگابایت
🎯 مثال واقعی
راهاندازی Redis Object Cache
برای سایتهای پرترافیک، Redis چندبرابر سرعت رو افزایش میده:
- Redis رو روی سرور نصب کن
- افزونه Redis Object Cache رو نصب کن
- توی wp-config.php اضافه کن:
define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_DATABASE', 0 );
define( 'WP_CACHE_KEY_SALT', 'icsd_' ); // یکتا برای هر سایت
۴. توی پنل، گزینه «Enable Object Cache» رو بزن
📝 خلاصه فصل
- هر ورودی sanitize، هر خروجی escape
- nonce برای جلوگیری از CSRF
- $wpdb->prepare برای جلوگیری از SQL injection
- Security Headers برای امنیت در سطح مرورگر
- Transients API برای کشگذاری ساده
- Browser cache و GZIP در .htaccess
- تصاویر رو بهینه کن (WebP، lazy loading)
- Query Monitor برای پیدا کردن گلوگاهها