`Cookie` i TypeScript
Denne artikel forklarer Cookie i TypeScript.
Vi gennemgår praktiske mønstre til at håndtere cookies sikkert og pålideligt både i browseren og på serveren.
YouTube Video
Cookie i TypeScript
Grundlæggende begreber om cookies
En cookie er en mekanisme til at gemme små strenge (navn=værdi-par) på klienten, oprettet via HTTP-headeren Set-Cookie eller document.cookie. Du kan styre deres adfærd med sikkerhedsattributter (HttpOnly, Secure, SameSite osv.).
Grundlæggende operationer i browseren: document.cookie
Nedenfor er det minimale eksempel på at skrive en cookie i browseren. Opret en cookie ved at tilføje en streng til 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');- Denne kode opretter en cookie, der udløber om 7 dage. Det er let at bruge på browsersiden, men da du ikke kan sætte
HttpOnly, bør du undgå at gemme følsomme oplysninger.
Læsning af cookies (browser)
Følgende funktion er en hjælpefunktion, der henter værdien af den cookie med et angivet navn fra document.cookie. document.cookie returneres som en streng, der er adskilt af et semikolon og et mellemrum ('; '). Derfor deler vi den op og søger efter den ønskede cookie.
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);- Denne funktion afkoder både cookiens navn og værdi for sikkert at kunne sammenligne og hente dem. Den håndterer duplikerede cookienavne og kodede specialtegn, hvilket gør det til en enkel, men robust implementering.
Forståelse og anvendelse af sikkerhedsattributter
Cookies har flere vigtige attributter, som hver især styrer sikkerheden og anvendelsesområdet.
- Attributten
HttpOnlyforhindrer, at cookien er tilgængelig fra JavaScript, hvilket hjælper med at afbøde XSS (cross-site scripting)-angreb. Bemærk, at du ikke kan sætteHttpOnlyfra browsersiden. - Attributten
Securebegrænser cookies til kun at blive sendt over HTTPS, hvilket reducerer risikoen for aflytning og manipulation. - Attributten
SameSitestyrer, om cookies sendes med forespørgsler på tværs af websteder, og hjælper med at forhindre CSRF (cross-site request forgery)-angreb. - Attributten
Pathangiver, for hvilke anmodningsstier cookien sendes, og attributtenDomainangiver det domæne, hvor cookien er gyldig. - Ved at sætte attributten
ExpiresellerMax-Agekan du styre cookiens udløb.
Eksempel på at tilføje SameSite / Secure i browseren (hvad der er muligt)
HttpOnly kan ikke sættes på klientsiden. Nedenfor er et eksempel på at tilføje SameSite og Secure på klientsiden. Dog gælder Secure kun på HTTPS-sider.
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=Laxer et sikkert og almindeligt valg. For stærkere restriktioner brugSameSite=Strict, men legitime navigationer fra eksterne sider kan stoppe med at virke.
Indstilling af cookies på serveren (Set-Cookie) (Node / TypeScript)
På serveren kan du tilføje HttpOnly via Set-Cookie-headeren, så sessionstyring bør ideelt set ske på serversiden. Nedenfor er et eksempel 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 sætter attributten
HttpOnlypå serversiden, bliver cookien utilgængelig fra JavaScript, hvilket gør det sværere for XSS (cross-site scripting)-angreb at stjæle den. Derudover kan du ved at tilføje attributtenSecure, så cookies altid sendes over HTTPS, forhindre aflytning og manipulation og forbedre kommunikationssikkerheden.
Implementering af serialisering/parsing af cookies (en serverside-hjælpefunktion)
Nedenfor er et simpelt værktøj på serversiden, der bygger en Set-Cookie-headerstreng.
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"
- Dette værktøj danner grundlaget for at oprette
Set-Cookiepå en skræddersyet server. Biblioteker kan håndtere mange flere kanttilfælde.
Forebyg forfalskning med signaturer (HMAC)
Det er farligt at gemme vigtige værdier direkte i cookies. Vi introducerer en metode, der signerer værdier på serveren for at opdage manipulation. Her bruger vi HMAC-SHA256. I produktion skal du også administrere tilbagekaldelse af tokens på serversiden.
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 denne metode kan du kontrollere, om cookie-værdien er blevet manipuleret. Medtag ikke signeringsnøglen i kildekoden; administrer den via sikre metoder såsom miljøvariabler.
Cookies og CSRF-afværgning (generelle mønstre)
Sessioner, der bruger cookies, har brug for CSRF-beskyttelse. Typiske afværgninger omfatter:.
- Sæt
SameSitetilLaxellerStrictfor at forhindre unødvendig cross-site-afsendelse. BrugSameSite=None; Securekun når cross-origin-kommunikation er nødvendig. - Brug CSRF-tokens, som valideres af serveren, til formularer og API-anmodninger. Gem ikke tokenet i en
HttpOnly-cookie; giv det i stedet via response body eller meta-tags, og lad JavaScript kun læse det, når det er nødvendigt. - Hvis tokenet kan tilgås fra JavaScript, skal du også implementere XSS-beskyttelser (CSP, output-escaping osv.).
- Kræv genautentificering for følsomme handlinger og ved login, og forebyg session-fixation-angreb.
Nedenfor er et sikkert klienteksempel, der sender CSRF-tokenet i en header. Dette forudsætter, at klienten allerede har modtaget tokenet fra serveren, f.eks. i response body.
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}- Hvis du angiver
credentials: 'same-origin', sendes kun cookies for samme origin. På serveren skal du validere værdien afX-CSRF-Token-headeren og verificere, at tokenet matcher. Hvis cross-site-forespørgsler er nødvendige, skal du konfigurere CORS omhyggeligt.
Cross-site (CORS) og forholdet til credentials
For at sende og modtage cookies i cross-origin-kommunikation skal klienten angive credentials: 'include', og serveren skal sætte Access-Control-Allow-Credentials: true. Begræns dog denne konfiguration til betroede origins, og brug ikke 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 af CORS og cookies er meget følsom fra et sikkerhedsmæssigt perspektiv. Administrer tilladte origins strengt med en whitelist, og undgå unødvendig cross-site-kommunikation. Håndhæv desuden HTTPS, når du bruger
SameSite=None; Secure, for at forhindre man-in-the-middle-angreb.
Eksempel: sikre indstillinger for sessionscookie med Express (TypeScript)
I praksis kan du bruge Express, cookie-biblioteket, express-session osv. Nedenfor er et simpelt eksempel med express og cookie-parser. I praksis skal secure sættes til true, og secret skal styres 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);- Ved at bruge
cookieParserssecret-funktion kan du nemt arbejde med signerede cookies. I virkelige applikationer bør du dog af hensyn til sikkerhed og skalerbarhed ikke gemme data direkte i cookies; brug i stedet et dedikeret sessionslager.
Cookie-præfikserne __Host- og __Secure-
Browsere håndhæver særlige regler for visse præfikser.
- Præfikset
__Secure-Hvis et cookienavn starter med__Secure-, erSecure-attributten påkrævet. - Præfikset
__Host-Hvis det starter med__Host-, erSecurepåkrævet, stien skal være/(rod), ogDomainmå ikke sættes.
Brug af disse reducerer fejlkonfigurationer og forbedrer sikkerheden.
Bedste praksis for cookies
For at håndtere cookies sikkert, overvej følgende punkter.
- Gem ikke følsomme oplysninger direkte i cookies. Foretræk et serverside-sessions-id til adgangstokens.
- Sæt sessionscookies med
HttpOnly,SecureogSameSite=Lax(eller Strict). - Udnyt præfikser som
__Host-og__Secure-. - Overvej signaturer (HMAC) og kryptering for at forhindre manipulation og aflytning.
- Aktiver
Secureog kræv HTTPS. - Tilstræb mindst mulige privilegier og korte udløbstider.
- Brug CSRF-tokens.
- Vær opmærksom på forskelle i
SameSite-adfærd på tværs af browsere, især ældre.
Almindelige misforståelser om cookies
Vedrørende cookies skal du være opmærksom på følgende almindelige misforståelser.
- 'Tilføjelse af
HttpOnlyfjerner virkningen af XSS.' SelvomHttpOnlyforhindrer adgang til cookies fra JavaScript, kan XSS stadig bruges til at udføre vilkårlige forespørgsler. Du bør også anvende CSRF-tokenvalidering, CSP (Content Security Policy) og sanitering af input. - '
Secureer unødvendig til lokal udvikling.' At simulere HTTPS og verificere adfærd selv i lokale miljøer forbedrer testnøjagtigheden. Som minimum bør HTTPS bruges i staging- og produktionsmiljøer. - 'Lange udløbstider er bekvemme.' Hvis du sætter lange cookie-levetider, øges den periode, hvor de kan misbruges, hvis de bliver stjålet. Du kan sætte kortere udløb og indføre periodisk genautentificering og tokenrotation.
Sammendrag
Selvom cookies er nemme at bruge, kan forkert håndtering introducere sikkerhedssårbarheder. For at håndtere dem korrekt med TypeScript er det vigtigt at forstå attributter som HttpOnly, Secure og SameSite og håndhæve sikre serverside-indstillinger. Ved ikke at gemme følsomme data direkte og kombinere signaturer med korte udløbstider kan du opnå sikker og pålidelig sessionstyring.
Du kan følge med i ovenstående artikel ved hjælp af Visual Studio Code på vores YouTube-kanal. Husk også at tjekke YouTube-kanalen.