TypeScript'te `Cookie`
Bu makale TypeScript'te Cookie konusunu açıklar.
Tarayıcıda ve sunucuda çerezleri güvenli ve güvenilir biçimde ele almak için pratik kalıpları adım adım inceliyoruz.
YouTube Video
TypeScript'te Cookie
Çerezlerin temel kavramları
Çerez, istemcide küçük dizeleri (ad=değer çiftleri) depolamak için bir mekanizmadır; Set-Cookie HTTP başlığı veya document.cookie ile oluşturulur. Davranışlarını güvenlik öznitelikleri (HttpOnly, Secure, SameSite vb.) ile kontrol edebilirsiniz.
Tarayıcıda temel işlemler: document.cookie
Aşağıda tarayıcıda çerez yazmanın en basit örneği yer alıyor. Bir çerezi document.cookie'ye bir dize ekleyerek oluşturun.
1// Set a simple cookie that expires in 7 days.
2// Note: Comments are in English per the user's preference.
3const setSimpleCookie = (name: string, value: string) => {
4 const days = 7;
5 const expires = new Date(Date.now() + days * 86400_000).toUTCString();
6 // name=value; Expires=...; Path=/
7 document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}; Expires=${expires}; Path=/`;
8};
9
10setSimpleCookie('theme', 'dark');- Bu kod, 7 gün sonra sona eren bir çerez oluşturur. Tarayıcı tarafında kullanımı kolaydır, ancak
HttpOnlyayarlanamadığı için hassas bilgileri depolamaktan kaçınmalısınız.
Çerezleri okuma (tarayıcı)
Aşağıdaki işlev, document.cookie içinden belirtilen ada sahip çerezin değerini alan bir yardımcı işlevdir. document.cookie, noktalı virgül ve boşluk ('; ') ile ayrılmış bir dize olarak döner. Bu nedenle onu parçalara ayırıp istenen çerezi arıyoruz.
1// Parse document.cookie and return value for given name or null if not found.
2const getCookie = (name: string): string | null => {
3 const cookies = document.cookie ? document.cookie.split('; ') : [];
4 for (const cookie of cookies) {
5 const [k, ...rest] = cookie.split('=');
6 const v = rest.join('=');
7 if (decodeURIComponent(k) === name) {
8 return decodeURIComponent(v);
9 }
10 }
11 return null;
12};
13
14// Example usage:
15const theme = getCookie('theme'); // => "dark" if set
16console.log('theme cookie:', theme);- Bu işlev, güvenli biçimde karşılaştırıp almak için çerezin hem adının hem de değerinin kodunu çözer. Yinelenen çerez adlarını ve kodlanmış özel karakterleri işler; bu da onu basit ama sağlam bir uygulama yapar.
Güvenli öznitelikleri anlama ve uygulama
Çerezlerin birkaç önemli niteliği vardır; bunların her biri güvenliği ve davranış kapsamını kontrol eder.
HttpOnlyniteliği çerezin JavaScript'ten erişilebilir olmasını engeller ve XSS (cross-site scripting) saldırılarını hafifletmeye yardımcı olur. Tarayıcı tarafındanHttpOnlyayarlanamayacağını unutmayın.Secureniteliği çerezlerin yalnızca HTTPS üzerinden gönderilmesini kısıtlar, dinleme ve kurcalama riskini azaltır.SameSiteniteliği çerezlerin siteler arası isteklerle gönderilip gönderilmeyeceğini kontrol eder ve CSRF (cross-site request forgery) saldırılarını önlemeye yardımcı olur.Pathniteliği çerezin gönderileceği istek yollarının kapsamını belirtir,Domainniteliği ise çerezin geçerli olduğu etki alanını belirtir.ExpiresveyaMax-Ageniteliğini ayarlayarak çerezin sona erme süresini kontrol edebilirsiniz.
Tarayıcıda SameSite / Secure ekleme örneği (mümkün olanlar)
HttpOnly istemci tarafında ayarlanamaz. Aşağıda istemci tarafında SameSite ve Secure ekleme örneği bulunmaktadır. Secure ise yalnızca HTTPS sayfalarında etkili olur.
1// Set cookie with SameSite and Secure attributes (Secure only effective over HTTPS).
2const setCookieWithAttributes = (name: string, value: string) => {
3 const maxAge = 60 * 60 * 24 * 7; // 7 days in seconds
4 // Note: HttpOnly cannot be set from JS; set it on server-side when you want to restrict JS access.
5 document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}; `
6 + `Max-Age=${maxAge}; `
7 + `Path=/; `
8 + `SameSite=Lax; `
9 + `Secure`;
10};
11
12setCookieWithAttributes('session_hint', 'true');SameSite=Laxgüvenli ve yaygın bir tercihtir. Daha sıkı kısıtlamalar içinSameSite=Strictkullanın; ancak dış sitelerden meşru yönlendirmeler çalışmayabilir.
Sunucuda çerez ayarlama (Set-Cookie) (Node / TypeScript)
Sunucuda Set-Cookie başlığıyla HttpOnly ekleyebilirsiniz; bu nedenle oturum yönetimi ideal olarak sunucu tarafında yapılmalıdır. Aşağıda Node'un http modülünü kullanan bir örnek yer alıyor.
1// A minimal Node HTTP server in TypeScript that sets a secure HttpOnly cookie.
2// This example uses built-in 'crypto' for a random session id.
3import http from 'http';
4import crypto from 'crypto';
5
6const server = http.createServer((req, res) => {
7 if (req.url === '/login') {
8 const sessionId = crypto.randomBytes(16).toString('hex');
9 // Set cookie with HttpOnly, Secure, SameSite and Path
10 // Expires is optional — Max-Age preferred for relative lifetimes.
11 res.setHeader('Set-Cookie', `sid=${sessionId}; `
12 + `HttpOnly; `
13 + `Secure; `
14 + `SameSite=Strict; `
15 + `Path=/; `
16 + `Max-Age=3600`
17 );
18 res.writeHead(302, { Location: '/' });
19 res.end();
20 return;
21 }
22
23 res.writeHead(200, { 'Content-Type': 'text/plain' });
24 res.end('Hello\n');
25});
26
27server.listen(3000, () => {
28 console.log('Server running on http://localhost:3000');
29});- Sunucu tarafında
HttpOnlyniteliğini ayarladığınızda çerez JavaScript'ten erişilemez hâle gelir ve XSS (cross-site scripting) saldırılarının onu çalmasını zorlaştırır. Ayrıca çerezlerin her zaman HTTPS üzerinden gönderilmesi içinSecureniteliğini ekleyerek dinlemeyi ve kurcalamayı önleyebilir, iletişim güvenliğini artırabilirsiniz.
Çerez serileştirme/ayrıştırma uygulaması (sunucu tarafı yardımcı)
Aşağıda Set-Cookie başlık dizesi oluşturan basit bir sunucu tarafı yardımcı araç bulunmaktadır.
1// Cookie serialization helper for server-side use.
2// Returns a properly formatted Set-Cookie header value.
3type CookieOptions = {
4 path?: string;
5 domain?: string;
6 maxAge?: number;
7 expires?: Date;
8 httpOnly?: boolean;
9 secure?: boolean;
10 sameSite?: 'Strict' | 'Lax' | 'None';
11};
12
13const serializeCookie = (name: string, value: string, opts: CookieOptions = {}): string => {
14 const parts: string[] = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
15
16 if (opts.maxAge != null) parts.push(`Max-Age=${Math.floor(opts.maxAge)}`);
17 if (opts.expires) parts.push(`Expires=${opts.expires.toUTCString()}`);
18 if (opts.domain) parts.push(`Domain=${opts.domain}`);
19 parts.push(`Path=${opts.path ?? '/'}`);
20 if (opts.httpOnly) parts.push('HttpOnly');
21 if (opts.secure) parts.push('Secure');
22 if (opts.sameSite) parts.push(`SameSite=${opts.sameSite}`);
23
24 return parts.join('; ');
25};
26
27// Example usage:
28const headerValue = serializeCookie('uid', 'abc123', {
29 httpOnly: true,
30 secure: true,
31 sameSite: 'Lax',
32 maxAge: 3600
33});
34console.log(headerValue);
35// => "uid=abc123; Max-Age=3600; Path=/; HttpOnly; Secure; SameSite=Lax"
- Bu yardımcı araç, özel bir sunucuda
Set-Cookieoluşturmanın temelini oluşturur. Kütüphaneler çok daha fazla uç durumu ele alabilir.
İmzalarla kurcalamayı önleme (HMAC)
Önemli değerleri doğrudan çerezlerde saklamak tehlikelidir. Kurcalamayı tespit etmek için değerleri sunucuda imzalayan bir yöntem sunuyoruz. Burada HMAC-SHA256 kullanıyoruz. Üretim ortamında, belirteç geçersiz kılmayı sunucu tarafında da yönetmeniz gerekir.
1// A simple HMAC signing and verification helper for cookies.
2// Signing prevents client from tampering cookie values.
3import crypto from 'crypto';
4
5const SECRET = 'replace_with_env_secret'; // store in env var in production
6
7const signValue = (value: string) => {
8 const hmac = crypto.createHmac('sha256', SECRET);
9 hmac.update(value);
10 return `${value}.${hmac.digest('hex')}`;
11};
12
13const verifySignedValue = (signed: string): string | null => {
14 const idx = signed.lastIndexOf('.');
15 if (idx === -1) return null;
16 const value = signed.slice(0, idx);
17 const sig = signed.slice(idx + 1);
18
19 const hmac = crypto.createHmac('sha256', SECRET);
20 hmac.update(value);
21 const expected = hmac.digest('hex');
22 // use timing-safe comparison in production
23 if (crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
24 return value;
25 }
26 return null;
27};
28
29// Example usage:
30const signed = signValue('userId=42');
31console.log('signed:', signed);
32console.log('verified:', verifySignedValue(signed)); // => "userId=42"
- Bu yöntemle, çerez değerinin kurcalanıp kurcalanmadığını kontrol edebilirsiniz. İmzalama anahtarını kaynak koda dahil etmeyin; ortam değişkenleri gibi güvenli yöntemlerle yönetin.
Çerezler ve CSRF azaltma (genel kalıplar)
Çerez kullanan oturumların CSRF korumasına ihtiyacı vardır. Tipik önlemler şunlardır:.
- Gereksiz siteler arası gönderimi önlemek için
SameSite'ıLaxveyaStrictolarak ayarlayın. Yalnızca çapraz kaynak iletişimi gerekli olduğundaSameSite=None; Securekullanın. - Formlar ve API istekleri için sunucu tarafından doğrulanan CSRF belirteçlerini kullanın.
HttpOnlyçerezinde belirteci saklamayın; bunun yerine, yanıt gövdesi veya meta etiketleri aracılığıyla sağlayın ve JavaScript'in onu yalnızca gerektiğinde okumasını sağlayın. - Belirtece JavaScript'ten erişilebiliyorsa, XSS korumalarını (CSP, çıktı kaçışlama vb.) de uyguladığınızdan emin olun.
- Hassas işlemler ve oturum açma için yeniden kimlik doğrulaması gerektirin ve oturum sabitleme saldırılarını önleyin.
Aşağıda, CSRF belirtecini bir başlıkta gönderen güvenli bir istemci örneği bulunmaktadır. Bu, istemcinin belirteci sunucudan zaten aldığını varsayar; örneğin yanıt gövdesinde.
1// Example of sending CSRF token safely in a header using fetch.
2// Assumes CSRF token was provided securely (e.g., via response body or meta tag).
3async function sendProtectedRequest(url: string, csrfToken: string) {
4 const res = await fetch(url, {
5 method: 'POST',
6 credentials: 'same-origin', // include cookies for same-site requests
7 headers: {
8 'Content-Type': 'application/json',
9 'X-CSRF-Token': csrfToken
10 },
11 body: JSON.stringify({ action: 'doSomething' })
12 });
13 return res;
14}credentials: 'same-origin'belirtirseniz, yalnızca aynı kökene ait çerezler gönderilir. Sunucuda,X-CSRF-Tokenbaşlığının değerini doğrulayın ve belirtecin eşleştiğini teyit edin. Çapraz köken istekleri gerekliyse, CORS'u dikkatle yapılandırın.
Siteler arası (CORS) ve credentials ile ilişkisi
Çapraz köken iletişiminde çerez göndermek ve almak için, istemci credentials: 'include' belirtmeli ve sunucu Access-Control-Allow-Credentials: true ayarlamalıdır. Ancak bu yapılandırmayı güvenilen kökenlerle sınırlandırın ve Access-Control-Allow-Origin: * kullanmayın.
1async function fetchCrossOriginData() {
2 // Example: cross-origin fetch sending cookies.
3 // Server must set Access-Control-Allow-Credentials: true
4 // and a specific trusted origin.
5 const res = await fetch('https://api.example.com/data', {
6 credentials: 'include', // send cookies only to trusted domains
7 method: 'GET'
8 });
9 return res;
10}- CORS ve çerezlerin birlikte kullanımı güvenlik açısından son derece hassastır. İzin verilen kökenleri bir beyaz listeyle sıkı biçimde yönetin ve gereksiz çapraz köken iletişiminden kaçının. Ayrıca,
SameSite=None; Securekullanırken ortadaki adam saldırılarını önlemek için HTTPS'i zorunlu kılın.
Örnek: Express ile güvenli oturum çerezi ayarları (TypeScript)
Pratikte Express, cookie kütüphanesi, express-session vb. kullanın. Aşağıda express ve cookie-parser kullanan basit bir örnek vardır. Pratikte, secure'ü true yapın ve secret'ı ortam değişkenleriyle yönetin.
1// Express example using cookie-parser and setting a secure httpOnly cookie.
2// npm install express cookie-parser @types/express @types/cookie-parser
3import express from 'express';
4import cookieParser from 'cookie-parser';
5
6const app = express();
7app.use(cookieParser(process.env.COOKIE_SECRET));
8
9app.post('/login', (req, res) => {
10 // authenticate user (omitted)
11 const sessionId = 'generated-session-id';
12 res.cookie('sid', sessionId, {
13 httpOnly: true,
14 secure: true, // require HTTPS in production
15 sameSite: 'lax',
16 maxAge: 1000 * 60 * 60 // 1 hour
17 });
18 res.json({ ok: true });
19});
20
21app.listen(3000);cookieParser'ınsecretözelliğini kullanarak imzalı çerezlerle kolayca çalışabilirsiniz. Ancak gerçek uygulamalarda, güvenlik ve ölçeklenebilirlik açısından verileri doğrudan çerezlerde depolamamalı; bunun yerine özel bir oturum deposu kullanmalısınız.
Çerez önekleri __Host- ve __Secure-
Tarayıcılar bazı önekler için özel kuralları zorunlu kılar.
__Secure-öneki Bir çerez adı__Secure-ile başlıyorsa,Secureözniteliği zorunludur.__Host-öneki__Host-ile başlıyorsaSecurezorunludur, yol/(kök) olmalı veDomainayarlanmamalıdır.
Bunları kullanmak yanlış yapılandırmayı azaltır ve güvenliği artırır.
Çerez en iyi uygulamaları
Çerezleri güvenli bir şekilde ele almak için aşağıdaki noktaları göz önünde bulundurun.
- Hassas bilgileri doğrudan çerezlerde depolamayın. Erişim belirteçleri için sunucu taraflı bir oturum kimliğini tercih edin.
HttpOnly,SecureveSameSite=Lax(veya Strict) ile oturum çerezleri ayarlayın.__Host-ve__Secure-gibi öneklerden yararlanın.- Kurcalama ve dinlemeyi önlemek için imzaları (HMAC) ve şifrelemeyi değerlendirin.
Secure'ü etkinleştirin ve HTTPS zorunlu olsun.- En az ayrıcalık ve kısa sona erme sürelerini hedefleyin.
- CSRF belirteçleri kullanın.
- Özellikle eski olanlar arasında, tarayıcılar arasındaki
SameSitedavranışı farklarına dikkat edin.
Çerezlerle ilgili yaygın yanlış kanılar
Çerezlerle ilgili olarak, aşağıdaki yaygın yanılgılara dikkat edin.
- '
HttpOnlyeklemek XSS'in etkisini ortadan kaldırır.'HttpOnlyçerezlere JavaScript tarafından erişilmesini engellese de, XSS yine de keyfi istekler göndermek için kullanılabilir. Ayrıca CSRF belirteci doğrulaması, CSP (İçerik Güvenlik Politikası) ve girdi arındırma da kullanmalısınız. - 'Yerel geliştirme için
Securegereksizdir.' Yerel ortamlarda bile HTTPS'i simüle etmek ve davranışı doğrulamak, test doğruluğunu artırır. En azından hazırlık (staging) ve üretim ortamlarında HTTPS kullanılmalıdır. - 'Uzun geçerlilik süreleri kullanışlıdır.' Çerezler için uzun yaşam süresi ayarlarsanız, çalınmaları hâlinde kötüye kullanılabilecekleri süre artar. Daha kısa sona erme süreleri belirleyebilir ve periyodik yeniden kimlik doğrulama ile belirteç döndürmeyi (token rotation) uygulayabilirsiniz.
Özet
Çerezler kullanımı kolay olsa da, yanlış yönetilmeleri güvenlik açıklarına yol açabilir. Bunları TypeScript ile doğru yönetmek için HttpOnly, Secure ve SameSite gibi öznitelikleri anlamak ve güvenli sunucu tarafı ayarlarını zorunlu kılmak önemlidir. Hassas verileri doğrudan saklamayarak ve imzaları kısa sona erme süreleriyle birleştirerek güvenli ve güvenilir bir oturum yönetimi sağlayabilirsiniz.
Yukarıdaki makaleyi, YouTube kanalımızda Visual Studio Code'u kullanarak takip edebilirsiniz. Lütfen YouTube kanalını da kontrol edin.