⚡ فصل ۱۴: کارایی و امنیت ووکامرس
یک فروشگاه آنلاین موفق باید سریع و امن باشد. در این فصل، تکنیکهای حرفهای بهینهسازی پرفورمنس و تامین امنیت ووکامرس را یاد میگیرید.
🚀 Object Cache با Redis
WordPress یک سیستم cache پیشفرض دارد که دادهها را در حافظه نگه میدارد، اما به طور پیشفرض فقط در طول یک request زنده است. با Redis این دادهها بین requestها هم میمانند:
نصب Redis در سرور
# Ubuntu/Debian
sudo apt update
sudo apt install redis-server php-redis
sudo systemctl enable redis
# تست
redis-cli ping
# باید جواب: PONG
افزونه Redis Object Cache
wp plugin install redis-cache --activate
تنظیم در wp-config.php
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_DATABASE', 0);
define('WP_REDIS_PREFIX', 'icsd_');
define('WP_REDIS_MAXTTL', 86400); // ۲۴ ساعت
define('WP_CACHE_KEY_SALT', 'icsd_woo_');
استفاده در کد
// کش پر هزینه
function get_top_products_cached() {
$cache_key = 'top_products_' . date('Y-m-d');
$cached = wp_cache_get($cache_key, 'icsd');
if ($cached !== false) return $cached;
// محاسبه سنگین
$products = expensive_top_products_query();
wp_cache_set($cache_key, $products, 'icsd', HOUR_IN_SECONDS);
return $products;
}
// پاکسازی هنگام تغییر
add_action('woocommerce_update_product', function($product_id) {
wp_cache_flush_group('icsd');
});
📄 Page Cache و استثنائات
افزونههای Page Cache (مثل WP Rocket، W3 Total Cache، LiteSpeed Cache) صفحات را بهصورت HTML استاتیک کش میکنند. اما برای ووکامرس، باید برخی صفحات استثنا شوند:
صفحات نیازمند استثنا
/cart/– سبد خرید/checkout/– پرداخت/my-account/– حساب کاربری/?add-to-cart=*– URL افزودن به سبد- صفحات با کوکی
woocommerce_*
تنظیم برای WP Rocket
// در فایل افزونه شما
add_filter('rocket_cache_reject_uri', function($urls) {
$urls[] = '/cart(/.*)?$';
$urls[] = '/checkout(/.*)?$';
$urls[] = '/my-account(/.*)?$';
$urls[] = '(.*)??add-to-cart=(.*)';
return $urls;
});
// کش رد شدن وقتی سبد دارد
add_filter('rocket_cache_reject_cookies', function($cookies) {
$cookies[] = 'woocommerce_items_in_cart';
$cookies[] = 'wp_woocommerce_session_';
return $cookies;
});
تنظیم برای LiteSpeed Cache
# در .htaccess
RewriteEngine On
RewriteCond %{HTTP_COOKIE} woocommerce_items_in_cart
RewriteRule .* - [E=Cache-Control:no-cache]
🗄️ بهینهسازی دیتابیس
۱. پاکسازی Transientهای قدیمی
-- حذف transient های منقضی
DELETE FROM wp_options
WHERE option_name LIKE '_transient_%'
OR option_name LIKE '_site_transient_%'
AND option_name NOT IN (
SELECT REPLACE(option_name, '_timeout', '')
FROM wp_options
WHERE option_name LIKE '_transient_timeout_%'
AND option_value > UNIX_TIMESTAMP()
);
-- حذف post revision قدیمی
DELETE FROM wp_posts WHERE post_type = 'revision';
-- حذف اتو-سیو ها
DELETE FROM wp_posts WHERE post_status = 'auto-draft';
۲. ایندکسهای مهم
-- ایندکس روی postmeta
ALTER TABLE wp_postmeta ADD INDEX idx_meta_key_value (meta_key(20), meta_value(20));
-- ایندکس روی woocommerce_order_items (اگر HPOS فعال نیست)
ALTER TABLE wp_woocommerce_order_items ADD INDEX idx_order_id (order_id);
ALTER TABLE wp_woocommerce_order_itemmeta ADD INDEX idx_meta_key (meta_key(20));
-- جستجوی فروش بر اساس تاریخ سریعتر
ALTER TABLE wp_wc_orders ADD INDEX idx_status_date (status, date_created_gmt);
۳. فعالسازی HPOS
High-Performance Order Storage سفارشها را در جدول جداگانه ذخیره میکند که ۱۰ تا ۲۰ برابر سریعتر است:
WooCommerce → Settings → Advanced → Features- فعال کردن High-Performance Order Storage
- ابتدا compatible mode، سپس فقط HPOS
۴. پاکسازی Cron قدیمی
// حذف وظایف Cron منقضی
add_action('admin_init', function() {
if (!isset($_GET['clean_cron'])) return;
$crons = _get_cron_array();
foreach ($crons as $timestamp => $hooks) {
foreach ($hooks as $hook => $events) {
if (strpos($hook, 'old_plugin_') === 0) { // الگوهای قدیمی
wp_clear_scheduled_hook($hook);
}
}
}
});
🖼️ بهینهسازی تصاویر
۱. تنظیم اندازههای مناسب
add_action('after_setup_theme', function() {
// اندازههای اصلی محصول
update_option('woocommerce_thumbnail_image_width', 400);
update_option('woocommerce_single_image_width', 800);
add_image_size('product-loop', 400, 400, true);
add_image_size('product-zoom', 1200, 1200, true);
add_image_size('product-mobile', 600, 600, true);
});
۲. WebP/AVIF خودکار
افزونههای پیشنهادی:
- ShortPixel – بهترین کیفیت، رایگان تا ۱۰۰ تصویر در ماه
- Imagify – WP Rocket family
- EWWW Image Optimizer – رایگان، نصب لوکال
- Modern Image Formats – رایگان، فقط WebP
۳. تبدیل دستی WebP
// تبدیل تصاویر آپلود شده به WebP
add_filter('wp_handle_upload', function($upload) {
if (strpos($upload['type'], 'image/') !== 0) return $upload;
if (in_array($upload['type'], ['image/webp', 'image/svg+xml'])) return $upload;
$file = $upload['file'];
$webp = preg_replace('/.(jpg|jpeg|png)$/i', '.webp', $file);
if (function_exists('imagewebp')) {
$img = $upload['type'] === 'image/png'
? imagecreatefrompng($file)
: imagecreatefromjpeg($file);
imagewebp($img, $webp, 80); // کیفیت ۸۰
imagedestroy($img);
}
return $upload;
});
۴. Srcset خودکار
// در قالب محصول، استفاده از تصاویر متناسب با دستگاه
add_filter('woocommerce_single_product_image_thumbnail_html', function($html, $attachment_id) {
$sizes = [
wp_get_attachment_image_url($attachment_id, 'product-mobile') . ' 600w',
wp_get_attachment_image_url($attachment_id, 'woocommerce_single') . ' 800w',
wp_get_attachment_image_url($attachment_id, 'product-zoom') . ' 1200w',
];
$srcset = implode(', ', $sizes);
$html = str_replace('![]()
⏳ Lazy Loading
WordPress 5.5+ بهصورت پیشفرض loading="lazy" روی img میگذارد، اما برای اطمینان:
// همه تصاویر محصول را lazy کن
add_filter('wp_get_attachment_image_attributes', function($attr, $attachment) {
if (!is_admin()) {
$attr['loading'] = 'lazy';
$attr['decoding'] = 'async';
}
return $attr;
}, 10, 2);
// به جز LCP image (تصویر اصلی محصول)
add_action('woocommerce_before_single_product_summary', function() {
add_filter('wp_get_attachment_image_attributes', 'eager_load_main_product_image', 10, 1);
});
function eager_load_main_product_image($attr) {
static $count = 0;
if ($count++ === 0) {
$attr['loading'] = 'eager';
$attr['fetchpriority'] = 'high';
}
return $attr;
}
🛡️ امنیت پایه
۱. غیرفعال کردن File Editor
// در wp-config.php
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true); // همچنین جلوی نصب افزونه از پنل را میگیرد
۲. Force HTTPS
// در wp-config.php
define('FORCE_SSL_ADMIN', true);
// در .htaccess
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
۳. تقویت کوکیها
add_filter('secure_signon_cookie', '__return_true');
add_filter('secure_logged_in_cookie', '__return_true');
// SameSite برای جلوگیری از CSRF
add_action('init', function() {
if (PHP_VERSION_ID >= 70300) {
ini_set('session.cookie_samesite', 'Strict');
}
});
۴. Disable XML-RPC (اگر استفاده نمیکنید)
add_filter('xmlrpc_enabled', '__return_false');
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wlwmanifest_link');
🔐 Nonce و Capability Check
هر فرم/AJAX در ووکامرس باید این دو را داشته باشد:
// در فرم
// در پردازش
add_action('admin_post_icsd_action', function() {
// ۱. چک Nonce
if (!isset($_POST['_icsd_nonce']) ||
!wp_verify_nonce($_POST['_icsd_nonce'], 'icsd_action')) {
wp_die('Nonce نامعتبر است', 403);
}
// ۲. چک Capability
if (!current_user_can('manage_woocommerce')) {
wp_die('دسترسی مجاز نیست', 403);
}
// ۳. Sanitize ورودیها
$product_id = absint($_POST['product_id'] ?? 0);
$title = sanitize_text_field($_POST['title'] ?? '');
$description = sanitize_textarea_field($_POST['description'] ?? '');
$email = sanitize_email($_POST['email'] ?? '');
$url = esc_url_raw($_POST['url'] ?? '');
// ۴. اعتبارسنجی منطقی
if (!$product_id || !get_post($product_id)) {
wp_die('محصول یافت نشد', 404);
}
// ۵. عملیات
update_post_meta($product_id, '_custom_field', $title);
// ۶. Redirect (نه echo)
wp_redirect(add_query_arg('saved', '1', wp_get_referer()));
exit;
});
برای AJAX
// JavaScript
fetch(ajax_url, {
method: 'POST',
body: new URLSearchParams({
action: 'icsd_save_data',
nonce: my_data.nonce,
product_id: 123,
})
});
// PHP
add_action('wp_ajax_icsd_save_data', function() {
check_ajax_referer('icsd_save_data', 'nonce');
if (!current_user_can('edit_products')) {
wp_send_json_error(['message' => 'دسترسی مجاز نیست'], 403);
}
// ... منطق ...
wp_send_json_success(['saved' => true]);
});
⏱️ Rate Limiting
جلوگیری از حملات brute-force روی login، checkout، و forms:
محدودیت لاگین
add_filter('authenticate', function($user, $username, $password) {
if (empty($username)) return $user;
$ip = $_SERVER['REMOTE_ADDR'];
$key = 'login_attempts_' . md5($ip);
$attempts = (int) get_transient($key);
if ($attempts >= 5) {
return new WP_Error('locked',
'تلاش بیش از حد. لطفاً ۱۵ دقیقه صبر کنید.');
}
if (is_wp_error($user)) {
set_transient($key, $attempts + 1, 15 * MINUTE_IN_SECONDS);
} else {
delete_transient($key); // پاک کردن در ورود موفق
}
return $user;
}, 30, 3);
محدودیت Checkout
add_action('woocommerce_checkout_process', function() {
$ip = $_SERVER['REMOTE_ADDR'];
$key = 'checkout_attempts_' . md5($ip);
$attempts = (int) get_transient($key);
if ($attempts >= 10) {
wc_add_notice('تعداد تلاش بیش از حد. لطفاً صبر کنید.', 'error');
return;
}
set_transient($key, $attempts + 1, HOUR_IN_SECONDS);
});
محدودیت Add to Cart (anti-bot)
add_filter('woocommerce_add_to_cart_validation', function($passed) {
$ip = $_SERVER['REMOTE_ADDR'];
$key = 'add_to_cart_' . md5($ip);
$count = (int) get_transient($key);
if ($count >= 30) { // حداکثر ۳۰ افزودن در دقیقه
wc_add_notice('سرعت غیرعادی! لطفاً آرامتر بزنید.', 'error');
return false;
}
set_transient($key, $count + 1, MINUTE_IN_SECONDS);
return $passed;
});
📜 Audit Log
ثبت تغییرات حساس برای پیگیری:
CREATE TABLE wp_icsd_audit_log (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED,
action VARCHAR(50) NOT NULL,
object_type VARCHAR(50),
object_id BIGINT UNSIGNED,
details TEXT,
ip_address VARCHAR(45),
user_agent VARCHAR(500),
created_at DATETIME NOT NULL,
KEY user_id (user_id),
KEY action (action),
KEY created_at (created_at)
);
function icsd_log_action($action, $object_type = '', $object_id = 0, $details = '') {
global $wpdb;
$wpdb->insert($wpdb->prefix . 'icsd_audit_log', [
'user_id' => get_current_user_id(),
'action' => $action,
'object_type' => $object_type,
'object_id' => $object_id,
'details' => is_array($details) ? wp_json_encode($details) : $details,
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
'user_agent' => substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 500),
'created_at' => current_time('mysql'),
]);
}
// مثالهای استفاده
add_action('woocommerce_order_status_changed', function($order_id, $old, $new) {
icsd_log_action('order_status_changed', 'order', $order_id, "از $old به $new");
}, 10, 3);
add_action('woocommerce_update_product', function($product_id) {
icsd_log_action('product_updated', 'product', $product_id);
});
add_action('user_register', function($user_id) {
icsd_log_action('user_registered', 'user', $user_id);
});
add_action('wp_login_failed', function($username) {
icsd_log_action('login_failed', 'user', 0, ['username' => $username]);
});
🙈 مخفی کردن نسخهها
// مخفی کردن نسخه WordPress
remove_action('wp_head', 'wp_generator');
add_filter('the_generator', '__return_empty_string');
// مخفی کردن از RSS
add_filter('the_generator', '__return_empty_string', 10, 2);
// مخفی کردن نسخه ووکامرس
add_filter('woocommerce_template_path', function($path) {
return $path;
});
remove_action('wp_head', [WC()->structured_data, 'enqueue_data']);
// حذف version از URL تصاویر و scriptها
function remove_query_strings($src) {
return remove_query_arg(['ver'], $src);
}
add_filter('script_loader_src', 'remove_query_strings', 10);
add_filter('style_loader_src', 'remove_query_strings', 10);
// حذف readme.html
add_action('init', function() {
if ($_SERVER['REQUEST_URI'] === '/readme.html') {
wp_redirect(home_url(), 301);
exit;
}
});
تغییر URL پیشفرض ادمین
// با افزونه WPS Hide Login - URL ورود را تغییر بده
// از /wp-admin به /icsd-secret-login
// یا دستی در .htaccess
// RewriteRule ^icsd-login/?$ /wp-login.php [QSA,L]
📝 خلاصه فصل
- Object Cache با Redis برای سرعت ۲ تا ۳ برابر
- Page Cache با استثنائات صحیح برای ووکامرس
- HPOS و ایندکسهای دیتابیس
- WebP و Lazy Loading برای تصاویر
- Nonce + Capability Check در همه فرمها
- Rate Limiting برای login و checkout
- Audit Log برای پیگیری تغییرات
- مخفی کردن نسخه و خبردهی
- SSL فعال + redirect به HTTPS
- Strong password policy
- 2FA برای مدیران (افزونه Wordfence یا iThemes)
- Backup روزانه (UpdraftPlus)
- Web Application Firewall (Wordfence, Cloudflare)
- Limit Login Attempts
- Disable directory browsing در .htaccess
- Update منظم WP Core، Plugins، Themes