مقدمه

یکی از ستون‌های اصلی امنیت در وب، «سیاست مبدأ یکسان» یا Same-Origin Policy است. این سیاست به طور کلی اجازه نمی‌دهد که یک اسکریپت از یک مبدأ (ترکیبی از پروتکل، دامنه و پورت) به محتوای یک صفحه از مبدأ دیگر دسترسی پیدا کند. این یک ویژگی امنیتی حیاتی است، اما گاهی اوقات ما نیاز داریم که بین دو زمینه (context) مختلف، مانند یک صفحه اصلی و یک <iframe> که از دامنه‌ی دیگری بارگذاری شده، ارتباط برقرار کنیم.

Cross-Context Messaging یا «پیام‌رسانی بین زمینه‌ای»، یک مکانیزم استاندارد و امن برای حل این مشکل فراهم می‌کند. این API به ما اجازه می‌دهد تا بین پنجره‌های مختلف (شامل تب‌ها، پاپ‌آپ‌ها و `iframe`ها) و حتی `Worker`ها، صرف نظر از مبدأ آنها، پیام ارسال و دریافت کنیم.

ارسال پیام با postMessage

قلب این API، متد postMessage() است. این متد روی شیء window زمینه هدف (مثلاً پنجره پاپ‌آپ یا contentWindow یک <iframe>) فراخوانی می‌شود و دو آرگومان اصلی می‌گیرد: postMessage(message, targetOrigin).

  • message: داده‌ای که می‌خواهید ارسال کنید. این داده می‌تواند تقریباً هر نوع داده‌ی قابل شبیه‌سازی (مانند رشته، عدد، آرایه، یا شیء ساده) باشد.
  • targetOrigin: این آرگومان امنیتی بسیار مهمی است. شما مشخص می‌کنید که پیام فقط در صورتی باید ارسال شود که مبدأ پنجره هدف با این مقدار برابر باشد. برای امنیت بیشتر، همیشه باید مبدأ دقیق (مثلاً 'https://example.com') را مشخص کنید. استفاده از '*' به معنی ارسال به هر مبدآ است و تنها زمانی باید استفاده شود که داده‌ی ارسالی حساس نباشد.
Copy Icon JAVASCRIPT
// In the parent page's script
const iframe = document.getElementById('my-iframe');

// It's best to send the message after the iframe has loaded
iframe.addEventListener('load', () => {
    const message = { userId: 42, action: 'login' };
    
    // Send the message to the iframe's window
    iframe.contentWindow.postMessage(message, 'https://iframe-origin.com');
});

در کد بالا، صفحه اصلی منتظر بارگذاری کامل <iframe> می‌ماند. سپس یک شیء پیام ساخته و آن را با استفاده از postMessage() به پنجره‌ی <iframe> ارسال می‌کند، اما تنها به این شرط که مبدأ فعلی <iframe> دقیقاً 'https://iframe-origin.com' باشد.

دریافت پیام‌ها

برای دریافت پیام‌ها، پنجره مقصد باید یک شنونده برای رویداد message روی شیء window خود ثبت کند.

تابع شنونده، یک شیء event دریافت می‌کند که حاوی اطلاعات مهمی است:

  • event.data: حاوی داده‌ی واقعی است که ارسال شده.
  • event.origin: مبدأ پنجره‌ای که پیام را ارسال کرده است. بررسی امنیتی این پراپرتی قبل از پردازش داده‌ها ضروری است.
  • event.source: ارجاعی به شیء window فرستنده، که می‌توان از آن برای ارسال پیام پاسخ استفاده کرد.
Copy Icon JAVASCRIPT
// In the iframe's script
window.addEventListener('message', (event) => {
    // SECURITY: Always verify the sender's origin
    if (event.origin !== 'https://parent-origin.com') {
        console.warn('Message from untrusted origin ignored:', event.origin);
        return;
    }

    // Process the received data
    const receivedData = event.data;
    console.log('Message from parent received:', receivedData);

    // Optional: Send a reply back to the parent window
    event.source.postMessage('Message received successfully!', event.origin);
});

در این کد، اسکریپت داخل <iframe> به رویداد message گوش می‌دهد. اولین و مهم‌ترین قدم، بررسی event.origin برای اطمینان از این است که پیام از یک منبع مورد اعتماد (صفحه والد) آمده است. در صورت تأیید، داده‌ها پردازش شده و یک پیام پاسخ به فرستنده اصلی ارسال می‌شود.

در این درس یاد گرفتیم که چگونه با استفاده از postMessage()، سد سیاست مبدأ یکسان» را به صورت ایمن دور بزنیم و بین زمینه‌های مختلف مرورگر ارتباط برقرار کنیم. کلید امنیت در این فرآیند، مشخص کردن دقیق مبدأ هدف توسط فرستنده و بررسی دقیق مبدأ فرستنده توسط گیرنده است. در درس بعدی، با Encoding API آشنا خواهیم شد که ابزارهایی برای کار با انکودینگ‌های مختلف کاراکتر و تبدیل رشته‌ها به داده‌های باینری فراهم می‌کند.