`Cookie` i TypeScript
Den här artikeln förklarar Cookie i TypeScript.
Vi går igenom praktiska mönster för att hantera cookies säkert och tillförlitligt både i webbläsaren och på servern.
YouTube Video
Cookie i TypeScript
Grundläggande begrepp om cookies
En cookie är en mekanism för att lagra små strängar (namn=värde-par) på klienten, skapade via HTTP-huvudet Set-Cookie eller document.cookie. Du kan styra deras beteende med säkerhetsattribut (HttpOnly, Secure, SameSite osv.).
Grundläggande operationer i webbläsaren: document.cookie
Nedan är ett minimalt exempel för att skriva en cookie i webbläsaren. Skapa en cookie genom att lägga till en sträng till document.cookie.
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');- Den här koden skapar en cookie som går ut om 7 dagar. Det är lätt att använda på webbläsarsidan, men eftersom du inte kan ange flaggan
HttpOnlybör du undvika att lagra känslig information.
Läsa cookies (webbläsare)
Följande funktion är en hjälpfunktion som hämtar värdet för den cookie som har ett angivet namn från document.cookie. document.cookie returneras som en sträng som är avgränsad med semikolon och ett mellanslag ('; '). Därför delar vi upp den och letar efter den önskade cookien.
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);- Den här funktionen avkodar både cookiens namn och värde för att säkert kunna jämföra och hämta dem. Den hanterar duplicerade cookienamn och kodade specialtecken, vilket gör den till en enkel men robust implementation.
Förstå och tillämpa säkra attribut
Cookies har flera viktiga attribut som var och ett styr säkerheten och beteendets räckvidd.
- Attributet
HttpOnlyförhindrar att cookien är åtkomlig från JavaScript, vilket hjälper till att motverka XSS (cross-site scripting). Observera att du inte kan sättaHttpOnlyfrån webbläsarsidan. Secure-attributet begränsar cookies till att endast skickas över HTTPS, vilket minskar risken för avlyssning och manipulering.SameSite-attributet styr om cookies skickas med förfrågningar mellan olika webbplatser och hjälper till att förhindra CSRF-attacker (cross-site request forgery).Path-attributet anger för vilka begärandesökvägar cookien skickas, ochDomain-attributet anger den domän där cookien är giltig.- Genom att ställa in attributet
ExpiresellerMax-Agekan du styra cookiens giltighetstid.
Exempel på att lägga till SameSite/Secure i webbläsaren (vad som är möjligt)
HttpOnly kan inte ställas in på klientsidan. Nedan visas ett exempel på att lägga till SameSite och Secure på klientsidan. Dock gäller Secure endast på HTTPS-sidor.
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=Laxär ett säkert och vanligt val. För starkare begränsningar, användSameSite=Strict, men legitima navigeringar från externa sajter kan sluta fungera.
Sätta cookies på servern (Set-Cookie) (Node/TypeScript)
På servern kan du lägga till HttpOnly via Set-Cookie-huvudet, så sessionshantering bör helst ske på serversidan. Nedan är ett exempel med Nodes http-modul.
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});- När du ställer in
HttpOnly-attributet på serversidan blir cookien oåtkomlig från JavaScript, vilket gör det svårare för XSS-attacker (cross-site scripting) att stjäla den. Dessutom kan du genom att lägga tillSecure-attributet så att cookies alltid skickas över HTTPS förhindra avlyssning och manipulering och förbättra kommunikationssäkerheten.
Implementering av serialisering/tolkning av cookies (en hjälpare på serversidan)
Nedan finns ett enkelt hjälpverktyg på serversidan som bygger en Set-Cookie-headersträng.
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"
- Det här verktyget utgör grunden för att skapa
Set-Cookiepå en egen server. Bibliotek kan hantera många fler kantfall.
Förhindra manipulation med signaturer (HMAC)
Det är riskabelt att lagra viktiga värden direkt i cookies. Vi introducerar en metod som signerar värden på servern för att upptäcka manipulation. Här använder vi HMAC-SHA256. I produktion måste du också hantera återkallelse av token på serversidan.
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"
- Med den här metoden kan du kontrollera om Cookie-värdet har manipulerats. Inkludera inte signeringsnyckeln i källkoden; hantera den genom säkra medel såsom miljövariabler.
Cookies och CSRF-skydd (generella mönster)
Sessioner som använder cookies behöver CSRF-skydd. Typiska motåtgärder inkluderar:.
- Sätt
SameSitetillLaxellerStrictför att förhindra onödig cross-site-sändning. AnvändSameSite=None; Secureendast när kommunikation mellan olika ursprung är nödvändig. - Använd CSRF‑token som valideras av servern för formulär och API‑begäranden. Förvara inte token i en
HttpOnly‑cookie; i stället, tillhandahåll den via svarskroppen eller metataggar, och låt JavaScript läsa den endast när det behövs. - Om token kan nås från JavaScript, se till att även implementera XSS‑skydd (CSP, output escaping, m.m.).
- Kräv återautentisering för känsliga åtgärder och vid inloggning, och förhindra sessionfixeringsattacker.
Nedan finns ett säkert klientexempel som skickar CSRF‑token i en header. Detta förutsätter att klienten redan har tagit emot token från servern, t.ex. i svarskroppen.
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}- Om du anger
credentials: 'same-origin'skickas endast cookies för samma ursprung. På servern, validera värdet i headernX-CSRF-Tokenoch verifiera att token matchar. Om cross‑site‑begäranden är nödvändiga, konfigurera CORS noggrant.
Cross-site (CORS) och relationen till credentials
För att skicka och ta emot cookies i kommunikation mellan olika ursprung måste klienten ange credentials: 'include' och servern måste ställa in Access-Control-Allow-Credentials: true. Begränsa dock denna konfiguration till betrodda ursprung och använd inte Access-Control-Allow-Origin: *.
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}- Kombinationen av CORS och cookies är mycket känslig ur ett säkerhetsperspektiv. Hantera tillåtna ursprung strikt med en vitlista och undvik onödig cross‑site‑kommunikation. När du använder
SameSite=None; Secure, tvinga dessutom igenom HTTPS för att förhindra man‑in‑the‑middle‑attacker.
Exempel: säkra inställningar för sessionscookies med Express (TypeScript)
I praktiken använder du Express, biblioteket cookie, express-session och så vidare. Nedan är ett enkelt exempel med express och cookie-parser. I praktiken, sätt secure till true och hantera secret via miljövariabler.
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);- Genom att använda
cookieParsermedsecretkan du enkelt arbeta med signerade cookies. I verkliga applikationer bör du dock, ur säkerhets- och skalbarhetssynpunkt, inte lagra data direkt i cookies; använd i stället en dedikerad sessionslagring.
Cookie-prefixen __Host- och __Secure-
Webbläsare verkställer särskilda regler för vissa prefix.
- Prefixet
__Secure-Om ett cookienamn börjar med__Secure-krävs attributetSecure. - Prefixet
__Host-Om det börjar med__Host-krävsSecure, sökvägen måste vara/(root) ochDomainfår inte vara satt.
Att använda dessa minskar felkonfiguration och förbättrar säkerheten.
Bästa praxis för cookies
För att hantera cookies på ett säkert sätt, tänk på följande punkter.
- Lagra inte känslig information direkt i cookies. Föredra ett sessions-ID på serversidan framför att lagra åtkomsttoken.
- Sätt sessionscookies med
HttpOnly,SecureochSameSite=Lax(eller Strict). - Utnyttja prefix som
__Host-och__Secure-. - Överväg signaturer (HMAC) och kryptering för att förhindra manipulation och avlyssning.
- Aktivera
Secureoch kräv HTTPS. - Sträva efter minsta privilegier och korta utgångstider.
- Använd CSRF-token.
- Var uppmärksam på skillnader i
SameSite-beteende mellan webbläsare, särskilt äldre.
Vanliga missuppfattningar om cookies
När det gäller cookies, var uppmärksam på följande vanliga missuppfattningar.
- 'Att lägga till
HttpOnlytar bort effekten av XSS.' Även omHttpOnlyförhindrar att cookies nås från JavaScript kan XSS fortfarande användas för att skicka godtyckliga förfrågningar. Du bör också använda CSRF-tokenverifiering, CSP (Content Security Policy) och sanering av indata. - '
Secureär onödigt för lokal utveckling.' Att simulera HTTPS och verifiera beteendet även i lokala miljöer förbättrar testernas noggrannhet. Åtminstone bör HTTPS användas i staging- och produktionsmiljöer. - 'Långa giltighetstider är bekväma.' Om du ställer in långa cookielivslängder ökar perioden under vilken de kan missbrukas om de stjäls. Du kan ställa in kortare giltighetstider och införa periodisk återautentisering och tokenrotation.
Sammanfattning
Även om cookies är lätta att använda kan felhantering av dem introducera säkerhetsbrister. För att hantera dem korrekt med TypeScript är det viktigt att förstå attribut som HttpOnly, Secure och SameSite och upprätthålla säkra inställningar på serversidan. Genom att inte lagra känsliga data direkt och kombinera signaturer med korta utgångstider kan du uppnå säker och tillförlitlig sessionshantering.
Du kan följa med i artikeln ovan med hjälp av Visual Studio Code på vår YouTube-kanal. Vänligen kolla även in YouTube-kanalen.