Afdæk hemmelighederne bag CORS (Cross-Origin Resource Sharing) og lær, hvordan du sikkert aktiverer anmodninger på tværs af domæner i dine webapplikationer. Denne omfattende guide dækker alt fra det grundlæggende til avancerede konfigurationer og sikrer problemfri og sikker kommunikation mellem forskellige oprindelser.
Afmystificering af CORS: En Omfattende Guide til Cross-Origin Resource Sharing
I nutidens forbundne web har applikationer ofte brug for at tilgå ressourcer fra forskellige oprindelser. Det er her, Cross-Origin Resource Sharing (CORS) kommer ind i billedet. CORS er en afgørende sikkerhedsmekanisme, der styrer, hvordan webbrowsere håndterer anmodninger fra én oprindelse (domæne, protokol og port) til en anden oprindelse. At forstå CORS er essentielt for enhver webudvikler for at bygge sikre og funktionelle webapplikationer.
Hvad er Same-Origin Policy?
Før vi dykker ned i CORS, er det vigtigt at forstå Same-Origin Policy (SOP). SOP er en fundamental sikkerhedsmekanisme implementeret i webbrowsere. Dens formål er at forhindre ondsindede scripts på ét website i at tilgå følsomme data på et andet website. En oprindelse er defineret ved kombinationen af protokollen (f.eks. HTTP eller HTTPS), domænet (f.eks. example.com) og portnummeret (f.eks. 80 eller 443). To URL'er betragtes som havende samme oprindelse, hvis de deler samme protokol, domæne og port.
Eksempel:
http://example.com/app1
oghttp://example.com/app2
- Samme oprindelse (samme protokol, domæne og port)https://example.com/app1
oghttp://example.com/app1
- Forskellig oprindelse (forskellig protokol)http://example.com:8080/app1
oghttp://example.com/app1
- Forskellig oprindelse (forskellig port)http://sub.example.com/app1
oghttp://example.com/app1
- Forskellig oprindelse (forskelligt subdomæne – betragtes som forskelligt domæne)
SOP begrænser scripts i at tilgå ressourcer fra en anden oprindelse, medmindre specifikke foranstaltninger, såsom CORS, er på plads for at tillade det.
Hvorfor er CORS nødvendigt?
Selvom Same-Origin Policy er afgørende for sikkerheden, kan den også være restriktiv. Mange moderne webapplikationer er afhængige af at hente data fra forskellige servere, såsom API'er eller content delivery networks (CDN'er). CORS giver en kontrolleret måde at lempe SOP på og tillade legitime anmodninger på tværs af oprindelser, samtidig med at sikkerheden opretholdes.
Overvej et scenarie, hvor en webapplikation hostet på http://example.com
skal hente data fra en API-server hostet på http://api.example.net
. Uden CORS ville browseren blokere denne anmodning på grund af SOP. CORS tillader API-serveren eksplicit at specificere, hvilke oprindelser der har tilladelse til at tilgå dens ressourcer, hvilket gør det muligt for webapplikationen at fungere korrekt.
Hvordan CORS virker: Det grundlæggende
CORS fungerer via en række HTTP-headere, der udveksles mellem klienten (browseren) og serveren. Serveren bruger disse headere til at informere browseren om, hvorvidt den må tilgå den anmodede ressource. Den centrale HTTP-header, der er involveret, er Access-Control-Allow-Origin
.
Scenarie 1: Simpel anmodning
En "simpel anmodning" er en GET-, HEAD- eller POST-anmodning, der opfylder specifikke kriterier (f.eks. er Content-Type
-headeren en af application/x-www-form-urlencoded
, multipart/form-data
eller text/plain
). I dette tilfælde sender browseren anmodningen direkte til serveren, og serveren svarer med Access-Control-Allow-Origin
-headeren.
Klientanmodning (fra http://example.com):
GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Serversvar (fra http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"data": "Noget data fra serveren"
}
I dette eksempel svarer serveren med Access-Control-Allow-Origin: http://example.com
, hvilket indikerer, at anmodninger fra http://example.com
er tilladt. Hvis oprindelsen i anmodningen ikke matcher værdien i Access-Control-Allow-Origin
-headeren (eller hvis headeren ikke er til stede), vil browseren blokere svaret og forhindre klientsidens script i at tilgå dataene.
Scenarie 2: Preflight-anmodning (for komplekse anmodninger)
For mere komplekse anmodninger, såsom dem der bruger HTTP-metoder som PUT, DELETE, eller dem med brugerdefinerede headere, udfører browseren en "preflight"-anmodning ved hjælp af HTTP OPTIONS-metoden. Denne preflight-anmodning spørger serveren om tilladelse, før den faktiske anmodning sendes. Serveren svarer med headere, der specificerer, hvilke metoder, headere og oprindelser der er tilladt.
Klientens preflight-anmodning (fra http://example.com):
OPTIONS /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Serversvar (fra http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header, Content-Type
Access-Control-Max-Age: 3600
Forklaring af headere:
Access-Control-Allow-Origin: http://example.com
- Indikerer, at anmodninger frahttp://example.com
er tilladt.Access-Control-Allow-Methods: GET, PUT, DELETE
- Specificerer de HTTP-metoder, der er tilladt for anmodninger på tværs af oprindelser.Access-Control-Allow-Headers: X-Custom-Header, Content-Type
- Angiver de tilladte brugerdefinerede headere i den faktiske anmodning.Access-Control-Max-Age: 3600
- Specificerer varigheden (i sekunder), som preflight-svaret kan caches af browseren. Dette hjælper med at reducere antallet af preflight-anmodninger.
Hvis serverens preflight-svar indikerer, at anmodningen er tilladt, fortsætter browseren med den faktiske anmodning. Ellers blokerer browseren anmodningen.
Klientens faktiske anmodning (fra http://example.com):
PUT /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
X-Custom-Header: some-value
Content-Type: application/json
{
"data": "Noget data der skal opdateres"
}
Serversvar (fra http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"status": "Data opdateret med succes"
}
Almindelige CORS-headere
Her er en oversigt over de vigtigste CORS-headere, du skal forstå:
Access-Control-Allow-Origin
: Denne header er den mest fundamentale. Den specificerer den eller de oprindelser, der har lov til at tilgå ressourcen. Mulige værdier inkluderer:- En specifik oprindelse (f.eks.
http://example.com
). *
(wildcard): Dette tillader anmodninger fra enhver oprindelse. Brug med forsigtighed, da det kan kompromittere sikkerheden, hvis følsomme data er involveret. Det bør generelt undgås i produktionsmiljøer.
- En specifik oprindelse (f.eks.
Access-Control-Allow-Methods
: Denne header specificerer de HTTP-metoder (f.eks. GET, POST, PUT, DELETE), der er tilladt for anmodninger på tværs af oprindelser. Den bruges i preflight-svaret.Access-Control-Allow-Headers
: Denne header angiver de brugerdefinerede headere, der er tilladt i anmodninger på tværs af oprindelser. Den bruges også i preflight-svaret.Access-Control-Allow-Credentials
: Denne header indikerer, om serveren tillader, at legitimationsoplysninger (f.eks. cookies, autorisations-headere) inkluderes i anmodninger på tværs af oprindelser. Den skal sættes tiltrue
, hvis du har brug for at sende legitimationsoplysninger. På klientsiden skal du også sættewithCredentials = true
på XMLHttpRequest-objektet.Access-Control-Expose-Headers
: Som standard eksponerer browsere kun et begrænset sæt af svar-headere (f.eks.Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
) til klientsidens scripts. Hvis du vil eksponere andre headere, skal du angive dem iAccess-Control-Expose-Headers
-headeren.Access-Control-Max-Age
: Denne header specificerer den maksimale tid (i sekunder), som en browser kan cache preflight-anmodningen. En længere værdi reducerer antallet af preflight-anmodninger og forbedrer ydeevnen.
CORS i forskellige server-side sprog
Implementering af CORS involverer typisk konfiguration af din server-side applikation til at sende de passende CORS-headere. Her er eksempler på, hvordan man gør dette i forskellige sprog og frameworks:
Node.js med Express
Du kan bruge cors
middleware-pakken:
const express = require('express');
const cors = require('cors');
const app = express();
// Aktiver CORS for alle oprindelser (BRUG MED FORSIGTIGHED I PRODUKTION)
app.use(cors());
// Alternativt, konfigurer CORS for specifikke oprindelser
// app.use(cors({
// origin: 'http://example.com'
// }));
app.get('/data', (req, res) => {
res.json({ message: 'Dette er CORS-aktiveret for alle oprindelser!' });
});
app.listen(3000, () => {
console.log('Serveren kører på port 3000');
});
Python med Flask
Du kan bruge Flask-CORS
-udvidelsen:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# Alternativt, konfigurer CORS for specifikke oprindelser
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})
@app.route("/data")
def hello():
return {"message": "Dette er CORS-aktiveret for alle oprindelser!"}
if __name__ == '__main__':
app.run(debug=True)
Java med Spring Boot
Du kan konfigurere CORS i din Spring Boot-applikation ved hjælp af annotationer eller konfigurationsklasser:
Brug af annotationer:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com") // Tillad anmodninger fra http://example.com
public class DataController {
@GetMapping("/data")
public String getData() {
return "Dette er CORS-aktiveret for http://example.com!";
}
}
Brug af konfiguration:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/data")
.allowedOrigins("http://example.com") // Tillad anmodninger fra http://example.com
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
}
PHP
"Dette er CORS-aktiveret for http://example.com!");
echo json_encode($data);
?>
CORS og sikkerhedsovervejelser
Selvom CORS muliggør anmodninger på tværs af oprindelser, er det afgørende at implementere det sikkert. Her er nogle vigtige overvejelser:
- Undgå at bruge
*
forAccess-Control-Allow-Origin
i produktion: Dette tillader anmodninger fra enhver oprindelse, hvilket kan udgøre en sikkerhedsrisiko. Specificer i stedet eksplicit de oprindelser, der har tilladelse til at tilgå dine ressourcer. - Valider
Origin
-headeren på server-siden: Selvom du bruger et framework, der håndterer CORS-konfiguration, er det god praksis at validereOrigin
-headeren på server-siden for at sikre, at anmodningen kommer fra en forventet oprindelse. - Vær opmærksom på
Access-Control-Allow-Credentials
: Hvis du bruger legitimationsoplysninger (f.eks. cookies, autorisations-headere), skal du sørge for at sætteAccess-Control-Allow-Credentials: true
på server-siden ogwithCredentials = true
på klientsiden. Vær dog opmærksom på, at brug afAccess-Control-Allow-Origin: *
ikke er tilladt, nårAccess-Control-Allow-Credentials
er sat tiltrue
. Du skal eksplicit specificere de tilladte oprindelser. - Konfigurer
Access-Control-Allow-Methods
ogAccess-Control-Allow-Headers
korrekt: Tillad kun de HTTP-metoder og -headere, der er nødvendige for, at din applikation fungerer korrekt. Dette hjælper med at reducere angrebsfladen. - Brug HTTPS: Brug altid HTTPS til dine webapplikationer og API'er for at beskytte data under overførsel.
Fejlfinding af CORS-problemer
CORS-problemer kan være frustrerende at fejlfinde. Her er nogle almindelige problemer og hvordan man løser dem:
- "No 'Access-Control-Allow-Origin' header is present on the requested resource": Dette er den mest almindelige CORS-fejl. Det betyder, at serveren ikke sender
Access-Control-Allow-Origin
-headeren i sit svar. Dobbelttjek din server-side konfiguration for at sikre, at headeren sendes korrekt. - "Response to preflight request doesn't pass access control check: It does not have HTTP ok status": Denne fejl indikerer, at preflight-anmodningen mislykkedes. Dette kan ske, hvis serveren ikke er konfigureret til at håndtere OPTIONS-anmodninger, eller hvis
Access-Control-Allow-Methods
- ellerAccess-Control-Allow-Headers
-headerne ikke er konfigureret korrekt. - "The value of the 'Access-Control-Allow-Origin' header in the response is not equal to the origin in the request": Denne fejl betyder, at oprindelsen i anmodningen ikke matcher værdien i
Access-Control-Allow-Origin
-headeren. Sørg for, at serveren sender den korrekte oprindelse i svaret. - Browser-caching: Nogle gange kan browsere cache CORS-svar, hvilket kan føre til uventet adfærd. Prøv at rydde din browser-cache eller bruge en anden browser for at se, om det løser problemet. Du kan også bruge
Access-Control-Max-Age
-headeren til at kontrollere, hvor længe browseren cacher preflight-svaret.
Fejlsøgningsværktøjer:
- Browserudviklerværktøjer: Brug browserens udviklerværktøjer (normalt tilgået ved at trykke på F12) til at inspicere netværksanmodninger og -svar. Kig efter CORS-relaterede headere og fejlmeddelelser.
- Online CORS-tjekkere: Der findes onlineværktøjer, der kan hjælpe dig med at teste din CORS-konfiguration. Disse værktøjer sender en anmodning til din server og analyserer svar-headerne for at identificere potentielle problemer.
Avancerede CORS-scenarier
Selvom de grundlæggende CORS-koncepter er relativt ligetil, er der nogle mere avancerede scenarier at overveje:
- CORS med subdomæner: Hvis du har brug for at tillade anmodninger fra flere subdomæner (f.eks.
app1.example.com
,app2.example.com
), kan du ikke blot bruge et wildcard som*.example.com
iAccess-Control-Allow-Origin
-headeren. I stedet skal du dynamisk generereAccess-Control-Allow-Origin
-headeren baseret påOrigin
-headeren i anmodningen. Husk at validere oprindelsen mod en hvidliste over tilladte subdomæner for at forhindre sikkerhedssårbarheder. - CORS med flere oprindelser: Hvis du har brug for at tillade anmodninger fra flere specifikke oprindelser, kan du ikke specificere flere oprindelser i
Access-Control-Allow-Origin
-headeren (f.eks. erAccess-Control-Allow-Origin: http://example.com, http://another.com
ugyldig). I stedet skal du dynamisk generereAccess-Control-Allow-Origin
-headeren baseret påOrigin
-headeren i anmodningen. - CORS og CDN'er: Når du bruger en CDN til at levere din API, skal du konfigurere CDN'en til at videresende
Origin
-headeren til din oprindelsesserver og til at cacheAccess-Control-Allow-Origin
-headeren korrekt. Konsulter din CDN-udbyders dokumentation for specifikke instruktioner.
Bedste praksis for CORS
For at sikre en sikker og effektiv CORS-implementering, følg disse bedste praksisser:
- Princippet om mindste privilegium: Tillad kun det minimale sæt af oprindelser, metoder og headere, der er nødvendige for, at din applikation fungerer korrekt.
- Gennemgå jævnligt CORS-konfiguration: Efterhånden som din applikation udvikler sig, skal du jævnligt gennemgå din CORS-konfiguration for at sikre, at den stadig er passende og sikker.
- Brug et framework eller bibliotek: Udnyt eksisterende frameworks eller biblioteker, der tilbyder indbygget CORS-support. Dette kan forenkle implementeringen og reducere risikoen for fejl.
- Overvåg for CORS-overtrædelser: Implementer overvågning for at opdage og reagere på potentielle CORS-overtrædelser.
- Hold dig opdateret: Hold dig ajour med de seneste CORS-specifikationer og sikkerhedsanbefalinger.
Konklusion
CORS er en kritisk sikkerhedsmekanisme, der muliggør kontrollerede anmodninger på tværs af oprindelser i webapplikationer. At forstå, hvordan CORS fungerer, og hvordan man konfigurerer det korrekt, er essentielt for enhver webudvikler. Ved at følge retningslinjerne og de bedste praksisser, der er beskrevet i denne omfattende guide, kan du bygge sikre og funktionelle webapplikationer, der problemfrit interagerer med ressourcer fra forskellige oprindelser.
Husk altid at prioritere sikkerhed og undgå at bruge alt for tilladende CORS-konfigurationer. Ved omhyggeligt at overveje sikkerhedskonsekvenserne af dine CORS-indstillinger kan du beskytte dine applikationer og data mod uautoriseret adgang.
Vi håber, at denne guide har hjulpet dig med at afmystificere CORS. God kodning!