SSL نصب کردید، آدرس سایت هم به HTTPS تغییر داد — اما مرورگر هنوز هشدار می‌دهد. قفل سبز نشان نمی‌دهد، یا یک علامت تعجب کنار آدرس می‌بینید. این احتمالاً Mixed Content است — یکی از رایج‌ترین مشکلاتی که بعد از نصب SSL گریبان صاحبان سایت را می‌گیرد.

خبر خوب: این مشکل کاملاً قابل حل است. در این راهنما توضیح می‌دهیم Mixed Content دقیقاً چیست، چرا خطرناک است، چطور پیدایش کنید، و چگونه برطرفش کنید.

Mixed Content چیست؟

Mixed Content یعنی یک صفحه‌ای که از طریق HTTPS (امن) بارگذاری می‌شود، اما بخشی از منابعش (تصاویر، اسکریپت‌ها، استایل‌ها، فونت‌ها، iframe ها) از طریق HTTP (ناامن) لود می‌شوند.

وقتی این اتفاق می‌افتد، اتصال بین کاربر و سایت «مختلط» است — بخشی رمزنگاری‌شده، بخشی باز. این مثل این است که یک در امن داشته باشید اما یک پنجره شکسته هم داشته باشید.

دو نوع Mixed Content

Passive Mixed Content

منابعی که محتوای صفحه را نمی‌توانند تغییر دهند: تصاویر، ویدیوها، فایل‌های صوتی. مرورگر معمولاً این موارد را بارگذاری می‌کند اما در نوار آدرس یک هشدار نشان می‌دهد — قفل با علامت تعجب، یا «Not Fully Secure».

Active Mixed Content

منابعی که می‌توانند محتوای صفحه را دستکاری کنند: فایل‌های JavaScript، CSS، iframe ها. این نوع بسیار خطرناک‌تر است. اگر یک فایل JS از HTTP بارگذاری شود، یک مهاجم Man-in-the-Middle می‌تواند آن فایل را در حین انتقال تغییر دهد و کد مخرب تزریق کند. به همین دلیل مرورگرهای مدرن Active Mixed Content را به‌طور کامل مسدود می‌کنند.

چرا Mixed Content مشکل جدی است؟

  • امنیت ناقص: HTTPS برای رمزنگاری طراحی شده. منابع HTTP در همان صفحه این رمزنگاری را می‌شکنند.
  • هشدار مرورگر: کاربران قفل شکسته یا «Not Secure» می‌بینند. این اعتماد را از بین می‌برد — به‌خصوص در صفحات پرداخت یا ثبت‌نام.
  • خرابی صفحه: منابع Active Mixed Content توسط مرورگر مسدود می‌شوند. اگر آن منابع JavaScript حیاتی باشند، صفحه ممکن است شکسته یا غیرقابل استفاده شود.
  • تأثیر سئو: گوگل HTTPS را به HTTP ترجیح می‌دهد. Mixed Content می‌تواند از اعتبار امنیتی سایت بکاهد.

چطور Mixed Content را پیدا کنیم؟

روش ۱: Developer Tools مرورگر

  1. صفحه مورد نظر را باز کنید.
  2. F12 را بزنید.
  3. به تب Console بروید.
  4. پیام‌هایی با متن «Mixed Content» یا «Mixed Content Warning» پیدا کنید. آدرس دقیق منبع مشکل‌دار را نشان می‌دهند.

در تب Network هم می‌توانید فیلتر کنید و منابعی که از HTTP لود می‌شوند را ببینید.

روش ۲: سرویس‌های آنلاین

سایت‌هایی مثل whynopadlock.com یا www.jitbit.com/sslcheck آدرس سایت شما را بررسی می‌کنند و لیست کاملی از منابع HTTP ارائه می‌دهند. برای سایت‌هایی با صفحات زیاد، این ابزارها کمک بزرگی هستند.

روش ۳: جستجو در دیتابیس وردپرس

در phpMyAdmin این کوئری SQL را اجرا کنید تا تمام پست‌هایی که آدرس HTTP دارند پیدا شوند:

SELECT ID, post_title FROM wp_posts
WHERE post_content LIKE '%http://%'
AND post_status = 'publish';

این کوئری فقط پست‌های منتشرشده را نشان می‌دهد. آدرس‌های خارجی (که با http:// سایت‌های دیگر شروع می‌شوند) هم نمایش داده می‌شوند — آن‌ها نیاز به بررسی جداگانه دارند.

روش‌های رفع Mixed Content

روش ۱: افزونه Really Simple SSL (وردپرس)

این افزونه رایگان برای اکثر سایت‌های وردپرسی بهترین نقطه شروع است. با یک کلیک اکثر آدرس‌های HTTP داخلی را به HTTPS تبدیل می‌کند، redirect HTTP به HTTPS را تنظیم می‌کند، و هدرهای امنیتی مناسب را اعمال می‌کند. بعد از نصب وردپرس، اولین افزونه‌ای است که باید نصب کنید.

روش ۲: Better Search Replace (وردپرس)

برای تغییر یکجا همه آدرس‌های HTTP در دیتابیس:

  1. افزونه Better Search Replace را نصب کنید.
  2. در Search، آدرس http://yourdomain.com را وارد کنید.
  3. در Replace، آدرس https://yourdomain.com را وارد کنید.
  4. همه جداول دیتابیس را انتخاب کنید.
  5. تیک «Run as dry run?» را بزنید تا ببینید چند مورد پیدا می‌شود (بدون تغییر واقعی).
  6. تیک را بردارید و دوباره اجرا کنید تا تغییرات واقعی اعمال شود.

این روش serialized data را هم درست مدیریت می‌کند — مشکلی که دستی کار کردن با دیتابیس گاهی ایجاد می‌کند.

روش ۳: تنظیم آدرس‌ها در wp-config.php

مطمئن شوید آدرس سایت در wp-config.php با HTTPS تنظیم شده:

define('WP_HOME','https://yourdomain.com');
define('WP_SITEURL','https://yourdomain.com');

همچنین در پیشخوان وردپرس، تنظیمات > عمومی را چک کنید — هر دو آدرس باید با https:// شروع شوند.

روش ۴: Redirect در .htaccess

برای اطمینان از اینکه همه ترافیک از طریق HTTPS می‌آید:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

این کد را به ابتدای فایل .htaccess اضافه کنید (بعد از خط RewriteEngine On اگر از قبل وجود دارد).

روش ۵: استفاده از آدرس نسبی

برای منابعی که در کد قالب لینک شده‌اند، می‌توانید از آدرس بدون پروتکل استفاده کنید:

<!-- به جای: -->
<img src="http://example.com/image.jpg">

<!-- این را بنویسید: -->
<img src="//example.com/image.jpg">

مرورگر به‌طور خودکار از همان پروتکل صفحه استفاده می‌کند. اما اگر منبع خارجی است و فقط HTTP دارد، این روش کمک نمی‌کند.

روش ۶: CSP Header برای ارتقا خودکار

با اضافه کردن این هدر به فایل .htaccess، مرورگر به‌صورت خودکار تمام منابع HTTP را به HTTPS ارتقا می‌دهد:

Header always set Content-Security-Policy "upgrade-insecure-requests"

این یک راه‌حل موقت مناسب است در حالی که دارید منابع را در کد درست می‌کنید — نه جایگزین دائمی.

Mixed Content در پلاگین‌ها و قالب وردپرس

یک منبع Mixed Content که اغلب نادیده گرفته می‌شود: خود قالب یا افزونه‌ها. برخی قالب‌ها و افزونه‌های قدیمی آدرس‌های CDN یا منابع خارجی را با http:// هاردکد کرده‌اند. در این موارد:

  • قالب و افزونه‌ها را به آخرین نسخه به‌روز کنید — نسخه‌های جدیدتر معمولاً این مشکلات را رفع کرده‌اند.
  • اگر قالب سفارشی دارید، در کد قالب دنبال http:// بگردید و تغییر دهید.
  • بعضی افزونه‌ها گزینه‌ای برای تغییر آدرس CDN خود دارند — تنظیمات افزونه را بررسی کنید.

نکته‌ای که کمتر به آن توجه می‌شود: برخی افزونه‌ها آدرس‌ها را مستقیماً در فایل‌های JS یا CSS هاردکد می‌کنند — نه در دیتابیس. Better Search Replace این فایل‌ها را تغییر نمی‌دهد. برای این موارد باید مستقیماً فایل‌های افزونه را ویرایش کنید یا افزونه را به‌روز کنید.

Mixed Content ناشی از منابع خارجی

گاهی منابع HTTP از سایت‌های خارجی وارد سایت شما می‌شوند: CDN قدیمی، ویجت‌های شبکه اجتماعی، embed های ویدیو، یا اسکریپت‌های تبلیغاتی. در این موارد:

  • بررسی کنید آیا منبع خارجی نسخه HTTPS دارد (اکثر سرویس‌های مدرن دارند).
  • آدرس embed را از http:// به https:// تغییر دهید.
  • اگر منبع خارجی اصلاً HTTPS ندارد، آن را با گزینه امن‌تری جایگزین کنید.

کدهای embed یوتیوب را بررسی کنید — نسخه‌های قدیمی ممکن است از http://www.youtube.com استفاده کنند که باید به https://www.youtube.com تغییر پیدا کند.

چک‌لیست بعد از رفع مشکل

  • کش مرورگر را پاک کنید (Ctrl+Shift+Delete) و صفحه را در حالت Incognito باز کنید.
  • کش افزونه کش وردپرس را پاک کنید.
  • کش Cloudflare را Purge کنید (اگر استفاده می‌کنید).
  • با ابزار whynopadlock.com یا Developer Tools یک بار دیگر بررسی کنید.
  • چند صفحه مختلف سایت را — نه فقط صفحه اصلی — بررسی کنید.

سوالات متداول

بعد از رفع مشکل چرا هنوز قفل سبز نشان نمی‌دهد؟

احتمالاً کش مرورگر نسخه قدیمی صفحه را نگه داشته. با Ctrl+Shift+Delete کش مرورگر را پاک کنید، یا صفحه را در حالت Incognito باز کنید. همچنین کش Cloudflare یا افزونه کش سرور را هم Purge کنید. اگر بعد از همه این کارها هنوز هشدار بود، احتمالاً یک منبع HTTP پنهان در صفحه هست که با Developer Tools باید دقیق‌تر پیدا کنید.

آیا CSP می‌تواند همه مشکلات Mixed Content را حل کند؟

هدر upgrade-insecure-requests بسیاری از موارد را به‌صورت خودکار ارتقا می‌دهد. اما این فقط برای منابعی که آدرس‌شان HTTPS دارند کار می‌کند — اگر یک سرور فقط HTTP دارد و HTTPS ندارد، مرورگر نمی‌تواند ارتقا دهد و آن منبع مسدود می‌شود. بنابراین CSP راه‌حل تکمیلی است، نه جایگزین درست کردن آدرس‌ها در کد.

چرا بعد از نصب SSL باز هم این مشکل پیش می‌آید؟

نصب SSL گواهی امنیتی را روی سرور فعال می‌کند — اما تمام آدرس‌های موجود در دیتابیس و کد سایت را تغییر نمی‌دهد. اگر تصاویر، لینک‌ها، و اسکریپت‌ها همچنان با http:// ذخیره شده‌اند، Mixed Content باقی می‌ماند. بعد از نصب SSL، حتماً دیتابیس و آدرس‌های هاردکد شده در قالب را هم به‌روز کنید. ترتیب صحیح: اول SSL نصب کنید، بعد redirect HTTP به HTTPS را فعال کنید، و در آخر دیتابیس را با Better Search Replace تمیز کنید.

جمع‌بندی

Mixed Content یکی از رایج‌ترین مشکلاتی است که بعد از مهاجرت به HTTPS پیش می‌آید — اما کاملاً قابل حل است. برای سایت‌های وردپرسی، افزونه Really Simple SSL در اکثر موارد کافی است. اگر مشکل عمیق‌تر بود، Better Search Replace دیتابیس را یکجا پاک‌سازی می‌کند.

وقتی مطمئن شدید هیچ منبع HTTP ای باقی نمانده، قفل سبز در نوار آدرس نشان می‌دهد که ارتباط کاربر با سایت شما کاملاً رمزنگاری‌شده است — هم برای امنیت واقعی، هم برای اعتمادی که کاربران به سایت شما دارند.