---
title: "تسلط بر هنر امنیت برنامه‌های وب پیش‌رونده"
---

# تسلط بر هنر امنیت برنامه‌های وب پیش‌رونده

برنامه‌های وب پیش‌رونده (PWAs) به استاندارد اصلی برای ارائه تجربه‌ای شبیه به اپلیکیشن در وب باز تبدیل شده‌اند. قدرت‌های اصلی آن‌ها — قابلیت کارآفلاین، اعلان‌های پوش، و قابلیت نصب — همچنین سطح‌های حمله جدیدی را معرفی می‌کنند که وب‌سایت‌های سنتی به ندرت با آن مواجه می‌شوند. این مقاله به‌عمق **دوره‌زندگی امنیتی یک PWA** می‌پردازد و ترکیبی از سخت‌سازی در سطح شبکه، محافظت‌های زمان اجرا و بهترین روش‌های عملیاتی را ارائه می‌دهد. در پایان، یک چک‌لیست خواهید داشت که می‌توانید برای هر پروژه‌ای به‌کار ببرید، چه یک خبرخوان ساده باشد و چه یک پلتفرم تجارت الکترونیک پیچیده.

> **TL;DR**: PWA خود را با HTTPS امن کنید، CSP سخت‌گیرانه‌ای اعمال کنید، سرویس‌ورکرها را در «sandbox» قرار دهید، تمام ورودی‌ها را اعتبارسنجی کنید و روتین مانیتورینگ مداومی اتخاذ کنید.

---

## 1. لایه حمل‌ونقل – خط اول دفاع

### 1.1 اعمال HTTPS در همه‌جا

تمام مرورگرهای مدرن برای ثبت سرویس‌ورکر **HTTPS** را اجباری می‌کنند. اما برخی دارایی‌ها (مثلاً تجزیه و تحلیل‌های شخص ثالث) ممکن است هنوز از طریق HTTP بارگذاری شوند که هشدارهای محتوای ترکیبی ایجاد کرده و دروازه‌ای برای حملات «گیرنده در میان» (MITM) می‌شود.

**مراحل کلیدی:**

1. دریافت یک گواهینامه TLS معتبر (Let’s Encrypt، Cloudflare و غیره).
2. تغییر مسیر تمام درخواست‌های `http://` به `https://` از طریق تنظیمات سرور.
3. فعال‌سازی **HSTS** (HTTP Strict Transport Security) برای اجبار مرورگرها به استفاده از HTTPS به مدت زمان از پیش تعریف‌شده.

```nginx
# Example NGINX snippet
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl http2;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    # TLS settings ...
}
```

> **نکته**: HSTS حملات کاهش سطح را حذف می‌کند، اما به‌دلیل اینکه یک‌بار تنظیم شد مرورگرها برای مدت زمان تعیین‌شده از HTTP خودداری می‌کنند، برنامه‌ریزی دقیق لازم است.

### 1.2 مهر‌گذاری گواهینامه (اختیاری)

برای PWAs با حساسیت بالا — بانکداری، سوابق بهداشتی — می‌توانید **مهر‌گذاری گواهینامه** را از طریق **Public Key Pinning Extension for HTTP (HPKP)** در نظر بگیرید. هرچند HPKP به‌دلیل خطرات استقرار در حال منسوخ شدن است، می‌توانید با هدرهای **Expect‑CT** که شفافیت گواهینامه را تحمیل می‌کند، امنیت مشابهی به‌دست آورید.

```http
Expect-CT: max-age=86400, enforce, report-uri="https://example.com/report"
```

---

## 2. سخت‌سازی سرویس‌ورکر

سرویس‌ورکرها قلب قابلیت‌های آفلاین یک PWA هستند. آن‌ها در یک رشته پس‌زمینه با امتیازات بالاتر اجرا می‌شوند و هدف اصلی برای بهره‌برداری هستند.

### 2.1 محدود کردن محدوده (Scope)

در هنگام ثبت سرویس‌ورکر، کم‌ترین `scope` ممکن را تعریف کنید. این کار جلوگیری می‌کند تا سرویس‌ورکر درخواست‌هایی را که خارج از حوزه موردنظرش هستند، رهگیری کند.

```javascript
navigator.serviceWorker.register('/sw.js', { scope: '/app/' })
  .then(reg => console.log('SW registered with scope:', reg.scope));
```

### 2.2 اعتبارسنجی یکپارچگی با Subresource Integrity (SRI)

اگر اسکریپت سرویس‌ورکر را از یک CDN بارگذاری می‌کنید، با **SRI** از این‌که کد دریافت‌شده با هش مورد انتظار مطابقت دارد، محافظت کنید.

```html
<script src="https://cdn.example.com/sw.js"
        integrity="sha384-abc123..."
        crossorigin="anonymous"></script>
```

### 2.3 Content Security Policy برای سرویس‌ورکرها

یک **CSP** سخت‌گیرانه می‌تواند مانع از بارگذاری اسکریپت‌های مخرب یا اتصال به مبدأهای غیرمجاز توسط سرویس‌ورکر شود.

```http
Content-Security-Policy: script-src 'self' https://trusted.cdn.com; 
                         connect-src 'self' https://api.example.com;
```

> **نکته**: از دستور `worker-src` (در مرورگرهای جدید پشتیبانی می‌شود) برای تعیین صریح مبدأهای اسکریپت‌ورکر استفاده کنید.

### 2.4 مدیریت حالت و اعتبارسنجی کش

هرگز به ورودی‌های کش به‌صورت کورکوران اعتمادی نداشته باشید. همیشه تازگی پاسخ‌های کش‌شده را بخصوص برای توکن‌های احراز هویت یا داده‌های شخصی اعتبارسنجی کنید.

```javascript
self.addEventListener('fetch', event => {
  const url = new URL(event.request.url);
  if (url.pathname.startsWith('/api/')) {
    // Bypass cache for dynamic data
    event.respondWith(fetch(event.request));
    return;
  }
  // Default cache‑first strategy for static assets
  event.respondWith(
    caches.match(event.request).then(cached => cached || fetch(event.request))
  );
});
```

---

## 3. محافظت‌های زمان اجرا – CSP، Permissions و Sandbox

### 3.1 CSP کامل‌ویژه

یک CSP خوب ریسک **Cross‑Site Scripting (XSS)** و **Data Injection** را کاهش می‌دهد. در زیر یک مثال سیاست برای یک PWA معمولی آمده است:

```http
Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'sha256-XYZ' https://analytics.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com wss://socket.example.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
```

- `script-src` شامل یک هش برای اسکریپت‌های درون‌خطی است تا از `unsafe-inline` جلوگیری شود.
- `frame-ancestors 'none'` جلوگیری از حملات clickjacking می‌کند.
- `connect-src` APIها و نقطه انتهایی WebSocket را لیست می‌کند.

### 3.2 Permissions Policy (قالب قبلی Feature‑Policy)

ویژگی‌های قدرتمند مرورگری که ممکن است به‌صورت ناخواسته توسط PWAها ارث‌بری شوند را محدود کنید.

```http
Permissions-Policy: geolocation=(), microphone=(), camera=(), payment=()
```

### 3.3 ویژگی Sandbox برای محتوای جاسازی‌شده

اگر PWA شما iframeهای شخص ثالث را میزبانی می‌کند، برای جلوگیری از اجرای اسکریپت و ناوبری، آن‌ها را «sandbox» کنید.

```html
<iframe src="https://maps.example.com"
        sandbox="allow-scripts allow-same-origin"
        loading="lazy"></iframe>
```

---

## 4. احراز هویت و دسترسی

### 4.1 احراز هویت مبتنی بر توکن با JWT

از **JSON Web Tokens (JWT)** برای احراز هویت بدون حالت استفاده کنید، اما هرگز آن‌ها را در `localStorage` ذخیره نکنید — به‌جای آن از **کوکی‌های Secure, HttpOnly** برای کاهش سرقت XSS استفاده کنید.

```http
Set-Cookie: token=eyJhbGciOi...; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600
```

### 4.2 چرخش توکن‌های Refresh

برای محدود کردن خسارت در صورت به‌دست آمدن توکن، توکن‌های Refresh را چرخانده (rotate) کنید.

1. کلاینت توکن Refresh می‌فرستد.
2. سرور آن را اعتبارسنجی کرده و هم توکن دسترسی جدید و هم توکن Refresh جدید صادر می‌کند.
3. توکن Refresh قدیمی در پایگاه داده نامعتبر می‌شود.

### 4.3 مقابله با CSRF

حتی با کوکی‌های SameSite، برای درخواست‌های POST که وضعیت را تغییر می‌دهند از **توکن‌های Anti‑CSRF** استفاده کنید.

```html
<input type="hidden" name="csrf_token" value="{{ .CSRFToken }}">
```

در سرور، توکن ارسال‌شده را با جلسه کاربر مقایسه کنید.

---

## 5. ذخیره‌سازی ایمن داده‌ها

PWAs می‌توانند داده را از طریق **IndexedDB**، **Cache API** و **Web Storage** ذخیره کنند. هر کدام ملاحظات امنیتی خاص خود را دارند.

| ذخیره‌سازی | مناسب برای | نکات امنیتی |
|-----------|------------|--------------|
| **Cache API** | دارایی‌های ثابت، بازگشت آفلاین | فقط منابع غیرقابل تغییر را کش کنید. از نام‌های کش نسخه‌بندی‌شده برای حذف داده‌های منقضی استفاده کنید. |
| **IndexedDB** | داده‌های ساخت‌یافته، تنظیمات کاربر | فیلدهای حساس را به‌صورت کلاینت‑ساید با Web Crypto API رمزنگاری کنید. |
| **LocalStorage / SessionStorage** | داده‌های کوچک، غیرحساس | از ذخیره‌سازی رازها اجتناب کنید. این داده‌ها برای هر اسکریپت صفحه در دسترس هستند. |

### 5.1 مثال: رمزنگاری داده‌های IndexedDB

```javascript
async function encryptAndStore(key, value) {
  const cryptoKey = await crypto.subtle.generateKey(
    { name: "AES-GCM", length: 256 },
    true,
    ["encrypt", "decrypt"]
  );
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const encoded = new TextEncoder().encode(value);
  const ciphertext = await crypto.subtle.encrypt(
    { name: "AES-GCM", iv },
    cryptoKey,
    encoded
  );
  const db = await openDB('secure-store', 1, {
    upgrade(db) { db.createObjectStore('secrets'); }
  });
  await db.put('secrets', { iv, ciphertext }, key);
}
```

---

## 6. مانیتورینگ، حسابرسی و واکنش به حوادث

امنیت یک پیکربندی یک‌باره نیست؛ یک چرخه‌ی پیوسته است.

### 6.1 اسکن خودکار

- از **OWASP ZAP** یا **Burp Suite** برای اسکن XSS، CSRF و هدرهای ناامن استفاده کنید.
- **Lighthouse** را در خط‌لوله CI/CD یکپارچه کنید تا رعایت استانداردهای PWA را تحمیل کند.

### 6.2 لاگ‌گیری زمان اجرا

خطاهای سرویس‌ورکر را جمع‌آوری کنید و به یک نقطه انتهایی امن برای تجزیه و تحلیل بفرستید.

```javascript
self.addEventListener('error', event => {
  fetch('https://logs.example.com/collect', {
    method: 'POST',
    body: JSON.stringify({ message: event.message, stack: event.error.stack })
  });
});
```

### 6.3 دفترچه‌ راهنمای حوادث

1. **تشخیص**: هشدار توسط ترافیک غیرعادی یا گزارش‌های نقض CSP فعال می‌شود.
2. **محافظت**: JWTهای به‌دست‌آمده را ابطال کنید، کلیدهای API را چرخانده کنید.
3. **از بین بردن**: کد آسیب‌پذیر را پچ کنید، کش سرویس‌ورکر را به‌روز کنید.
4. **به‌سازی**: نسخه جدید را مستقر کنید، نظارت بر تکرار را ادامه دهید.
5. **پس‌تحلیل**: علت ریشه‌ای را مستند کنید و چک‌لیست امنیتی را به‌روزرسانی کنید.

---

## 7. نمای کلی تصویری – لایه‌های امنیتی در یک PWA

```mermaid
flowchart TB
    subgraph "Transport Layer"
        H["\"HTTPS\""]
        S["\"HSTS\""]
    end
    subgraph "Service Worker"
        SW["\"Scope Limitation\""]
        CS["\"Cache Validation\""]
    end
    subgraph "Runtime"
        CSP["\"Content Security Policy\""]
        PP["\"Permissions Policy\""]
        SAN["\"Sandboxed iFrames\""]
    end
    subgraph "Auth & Data"
        JWT["\"Secure Cookies\""]
        REF["\"Refresh Rotation\""]
        ENC["\"IndexedDB Encryption\""]
    end
    subgraph "Monitoring"
        SCAN["\"OWASP ZAP\""]
        LOG["\"Runtime Logging\""]
    end

    H --> SW --> CSP --> JWT --> SCAN
    S --> SW
    CS --> PP
    PP --> ENC
    LOG --> SCAN
```

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

---

## 8. چک‌لیست – مرجع سریع برای یک PWA ایمن

- [ ] تمام محتوا از طریق HTTPS با HSTS فعال سرو شود.
- [ ] سرویس‌ورکرها را با کوچک‌ترین `scope` ممکن ثبت کنید.
- [ ] اگر اسکریپت سرویس‌ورکر را از CDN می‌گیرید، با Subresource Integrity حفاظت کنید.
- [ ] CSP سخت‌گیرانه‌ای اعمال کنید، شامل `worker-src` و هش‌های اسکریپت.
- [ ] از Permissions‑Policy برای غیرفعال‌سازی ویژگی‌های مرورگر که استفاده نمی‌شوند، استفاده کنید.
- [ ] توکن‌های احراز هویت را در کوکی‌های Secure, HttpOnly ذخیره کنید؛ هرگز در localStorage نگهداری نکنید.
- [ ] توکن‌های Refresh را چرخانده و توکن‌های CSRF را برای درخواست‌های تغییر وضعیت اعتبارسنجی کنید.
- [ ] داده‌های حساس را در IndexedDB رمزنگاری کنید.
- [ ] اسکن OWASP ZAP خودکار را بر روی هر Pull Request اجرا کنید.
- [ ] لاگ‌گیری زمان واقعی خطاهای سرویس‌ورکر را تنظیم کنید.
- [ ] یک دفترچهٔ راهنمای واکنش به حادثه داشته باشید.

---

## 9. پرسش‌های متداول

**س۱: آیا PWAs برای امنیت به سرویس‌ورکر نیاز دارند؟**  
خیر. اقدامات امنیتی مانند HTTPS، CSP و کوکی‌های ایمن به‌صورت مستقل کار می‌کنند. اما سرویس‌ورکر جایی است که بیشتر حملات زمان اجرا بروز می‌یابند، بنابراین نیاز به سخت‌سازی بیشتری دارد.

**س۲: می‌توانم `unsafe-inline` را در CSP برای استایل‌ها استفاده کنم؟**  
ترجیحاً از آن خودداری کنید. به‌جای آن استایل‌های درون‌خطی را هش یا nonce کنید یا آن‌ها را به فایل‌های CSS خارجی منتقل کنید.

**س۳: هر چند یکبار باید گواهینامه TLS را تجدید کنم؟**  
گواهینامه‌های Let’s Encrypt هر ۹۰ روز صادر می‌شوند؛ خودکارسازی تجدید توصیه می‌شود. برای گواهینامه‌های تجاری یا خودامضا، حداکثر اعتبار ۱ سال پیشنهاد می‌شود.

---

## 10. جمع‌بندی

PWAs مرز بین تجربه‌های بومی و وب را مخفی می‌کنند و قابلیت‌های قدرتمندی ارائه می‌دهند که سطح حمله را هم گسترش می‌دهند. با لایه‌بندی امنیت در حمل‌ونقل، محدود کردن دامنه سرویس‌ورکر، اعمال یک Content Security Policy دقیق و اتخاذ روش‌های احراز هویت مستحکم، می‌توانید PWA خود را بدون قربانی کردن کارایی یا تجربه کاربری امن کنید.

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

---

## <span class='highlight-content'>همچنین ببینید</span>

- [MDN Web Docs – Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)
- [OWASP Top Ten Project](https://owasp.org/www-project-top-ten/)
- [Mozilla – Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)
- [Web.dev – HTTPS and HSTS](https://web.dev/transport-layer-security/)
- [RFC 6797 – HTTP Strict Transport Security (HSTS)](https://tools.ietf.org/html/rfc6797)