Erişilebilirlik & Güvenlik
İlan 1 özel · İlan 1

Erişilebilirlik (a11y) ve güvenlik

İlan açıkça "performans, güvenlik ve accessibility standartlarını belirleyip uygulayabilmek" diyor — bu sitedeki tek eksik konuydu, şimdi kapatıyoruz.

Erişilebilirlik — temel ilkeler

İlkePratikte ne demek
Semantik HTML önce<button> yerine <div onClick> kullanma — buton zaten klavye odaklanabilir, Enter/Space ile tetiklenir, ekran okuyucu "buton" der. Bunları sıfırdan ARIA ile taklit etmek gereksiz iştir.
Klavye ile her şey yapılabilmeliMouse olmadan Tab/Enter/Esc ile tüm akış (form doldurma, modal kapama) tamamlanabilmeli
Renk kontrastıMetin/arka plan kontrast oranı en az 4.5:1 (WCAG AA) — Lighthouse bunu otomatik kontrol eder
ARIA — son çareSemantik HTML yetmediğinde kullan (role, aria-label, aria-describedby). Gereksiz ARIA, hiç ARIA olmamasından daha kötü olabilir.

Erişilebilir bir form alanı

function FaturaNoAlani({ value, onChange, error }: Props) {
  return (
    <div>
      <label htmlFor="fatura-no">Fatura numarası</label>
      <input
        id="fatura-no"
        value={value}
        onChange={(e) => onChange(e.target.value)}
        aria-invalid={!!error}
        aria-describedby={error ? "fatura-no-error" : undefined}
      />
      {error && (
        <p id="fatura-no-error" role="alert">{error}</p>
      )}
    </div>
  );
}
// label + htmlFor: ekran okuyucu "Fatura numarası" der, sadece placeholder değil
// aria-describedby: hata mesajını input'a bağlar, ekran okuyucu hatayı da okur

Erişilebilir bir modal iskeleti

function Modal({ onClose, children }: Props) {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    ref.current?.focus();                 // açılınca odak modala geçsin
    function onKey(e: KeyboardEvent) {
      if (e.key === "Escape") onClose();   // Esc ile kapanabilsin
    }
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [onClose]);

  return (
    <div role="dialog" aria-modal="true" ref={ref} tabIndex={-1}>
      {children}
    </div>
  );
}
// Eksik olan (gerçek üretimde eklenmesi gereken): focus trap —
// Tab tuşu modal dışına çıkmamalı, kapanınca odak açan butona dönmeli.
💡
Test etmenin en hızlı yoluChrome DevTools'ta Lighthouse > Accessibility sekmesi otomatik bir skor ve somut hata listesi verir (eksik alt, düşük kontrast, label'sız input vb.). axe-core kütüphanesi de CI'a entegre edilip her PR'da otomatik taranabilir.

Güvenlik — frontend'in sorumlu olduğu kısım

Backend güvenliği (auth, yetkilendirme, SQL injection) ayrı bir konu — burada frontend tarafında gerçekten senin kontrolünde olan 3 şey var.

1. XSS (Cross-Site Scripting)

React varsayılan olarak {deger} ile render edilen her şeyi kaçışlar — XSS'e karşı yerleşik koruma budur. Tehlike, bunu dangerouslySetInnerHTML ile bilerek devre dışı bıraktığın anda başlar.

// GÜVENLİ — React varsayılan olarak metni kaçışlar (escape)
<p>{kullaniciYorumu}</p>

// TEHLİKELİ — kullanıcı girdisini asla ham HTML olarak basma
<div dangerouslySetInnerHTML={{ __html: kullaniciYorumu }} />

// Gerekiyorsa (ör. CMS'ten gelen zengin metin) önce sanitize et:
import DOMPurify from "dompurify";
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(cmsIcerik) }} />
⚠️
Bu sitenin kendi kod örneği — dürüst bir itirafCodeBlock.tsx bileşeni dangerouslySetInnerHTML kullanıyor (kod renklendirme için). Güvenli, çünkü içeriği BEN yazdım, kullanıcıdan gelmiyor. Mülakatta sorulursa: "dangerouslySetInnerHTML kullanmak otomatik olarak güvensiz değildir — güvensiz olan, kullanıcıdan gelen veriyi sanitize etmeden orada kullanmaktır."

2. CSRF ve auth token saklama

İlan 2 SharePoint sayfasındaki X-RequestDigest zaten bir CSRF önlemiydi. Frontend'te en sık yapılan hata: JWT/auth token'ı localStorage'a yazmak — XSS ile çalınabilir. Daha güvenli yol: HttpOnly cookie.

Set-Cookie: token=xyz; HttpOnly; Secure; SameSite=Strict
// HttpOnly  → JavaScript (document.cookie) token'ı OKUYAMAZ — XSS ile çalınamaz
// Secure    → sadece HTTPS üzerinden gönderilir
// SameSite  → başka bir siteden yapılan isteklerde cookie otomatik eklenmez (CSRF azaltır)
💡
Bu sitenin localStorage kullanımı neden güvenliBu site de localStorage kullanıyor (checklist ilerlemesi, STAR taslakların) ama kimlik/oturum bilgisi DEĞİL — sadece hassas olmayan, kaybolsa da sorun olmayan UI state'i. Kural: "localStorage'a ne koyduğunu, çalınsa ne olacağını düşünerek koy."

3. Bağımlılık (dependency) güvenliği

npm audit düzenli çalıştırılır, bilinen CVE'li paketler güncellenir. Bu proje de @reduxjs/toolkit gibi bağımlılıklar kullanıyor — production'a çıkmadan önce npm audit kontrolü rutin bir adım olmalı.

Egzersizler

1) Bir tasarımcı 'bu buton çok kare duruyor, div ile yuvarlak yapalım, tıklama olayını onClick ile bağlarız' dedi. Nasıl cevap verirsin?
Görsel olarak <button>'u border-radius ile istediğin kadar yuvarlaklaştırabilirsin — semantiği kaybetmene gerek yok. <div onClick> kullanırsan klavye ile odaklanamaz, Enter'a basınca tetiklenmez, ekran okuyucu onu "buton" olarak duyurmaz — bunları elle (tabIndex, role="button", onKeyDown) yeniden inşa etmek, zaten var olan bir özelliği taklit etmek olur.
2) 'localStorage'a JWT token koymak neden riskli, alternatif ne?
localStorage, sayfadaki HERHANGİ bir JavaScript tarafından (senin kodun dahil, üçüncü parti bir script/XSS açığı dahil) okunabilir — bir XSS açığı bulunursa saldırgan token'ı doğrudan çalabilir. HttpOnly cookie'de token JavaScript'e hiç görünmez, tarayıcı onu otomatik gönderir; XSS olsa bile token çalınamaz (CSRF riski için de SameSite ile önlem alınır).