28/12/2022
- Hvad er CORS og hvorfor er det vigtigt for RESTful API'er?
- Grundlæggende om CORS: Same-Origin Policy og dens begrænsninger
- Hvorfor CORS er nødvendigt for RESTful API'er
- Hvordan fungerer CORS?
- Konfiguration af CORS i forskellige backend-frameworks
- Almindelige CORS-fejl og løsninger
- Bedste praksis for CORS-konfiguration
- Konklusion
Hvad er CORS og hvorfor er det vigtigt for RESTful API'er?
I den moderne webudvikling er det almindeligt, at frontend-applikationer, ofte bygget med frameworks som React, Vue eller Angular, kommunikerer med backend RESTful API'er. Denne kommunikation sker ofte på tværs af forskellige domæner eller porte. Her kommer Cross-Origin Resource Sharing (CORS) ind i billedet. CORS er en essentiel sikkerhedsmekanisme, der er indbygget i moderne webbrowsere. Uden korrekt konfiguration kan browsere blokere disse anmodninger af sikkerhedsmæssige årsager, hvilket kan føre til frustration og funktionsfejl i applikationer.

Denne artikel vil dykke ned i, hvad CORS er, hvorfor det er så vigtigt for RESTful API'er, hvordan det fungerer, og hvordan man implementerer det korrekt på tværs af forskellige backend-teknologier. Vi vil også se på almindelige fejl og bedste praksis for at sikre en sikker og effektiv kommunikation.
Grundlæggende om CORS: Same-Origin Policy og dens begrænsninger
For at forstå CORS er det vigtigt først at forstå Same-Origin Policy (SOP). SOP er en fundamental sikkerhedsfunktion i browsere, der forhindrer en webside fra ét domæne i at interagere med ressourcer fra et andet domæne. Dette gælder for JavaScript-anmodninger, der foretages via AJAX eller fetch API'et. Formålet er at beskytte brugere mod ondsindede websteder, der kunne forsøge at få adgang til følsomme data fra andre sider, som brugeren er logget ind på (f.eks. bankoplysninger via cookies).
Et 'origin' defineres af kombinationen af protokol, domænenavn og portnummer. For eksempel er https://www.example.com og https://api.example.com forskellige oprindelser. Ligeledes er http://localhost:8080 og http://localhost:3000 også forskellige oprindelser. SOP sikrer, at kun scripts fra samme oprindelse kan tilgå ressourcer fra den oprindelse.

Hvorfor CORS er nødvendigt for RESTful API'er
Mens SOP er afgørende for at forhindre ondsindede handlinger, begrænser det også legitime udviklingsscenarier. Mange moderne applikationer har en arkitektur, hvor frontend og backend er adskilt. En frontend hostet på https://frontend.example.com kan have brug for at kalde en API hostet på https://api.example.com. Uden CORS ville disse anmodninger blive blokeret af browseren, hvilket gør det umuligt for applikationen at fungere som tiltænkt.
CORS giver en måde for serveren at specificere, hvilke oprindelser, HTTP-metoder og headers der er tilladt for tværgående anmodninger. Ved at tilføje specifikke HTTP-headers til svaret kan serveren informere browseren om, at den godkender tværgående anmodninger fra en bestemt oprindelse.
Almindelige scenarier, hvor CORS er relevant:
- Single Page Applications (SPAs): En SPA hostet på ét domæne (f.eks.
https://app.example.com) der kalder en API på et andet domæne (f.eks.https://api.example.com). - Udviklingsmiljøer: En frontend, der kører lokalt på
http://localhost:3000, der kalder en backend, der kører påhttp://localhost:8080. - Tredjeparts API-integrationer: Integration med eksterne tjenester som betalingsgateways eller analyseplatforme.
- Mikroservices: Forskellige services inden for en applikation, der kører på forskellige subdomæner eller porte.
Hvordan fungerer CORS?
CORS-interaktioner involverer typisk to typer anmodninger: Simple Requests og Preflighted Requests.

1. Simple Requests
En anmodning betragtes som 'simpel', hvis den opfylder bestemte kriterier, herunder:
- Bruger en af de følgende HTTP-metoder:
GET,HEAD, ellerPOST. POST-anmodninger må kun sende data medContent-Type:application/x-www-form-urlencoded,multipart/form-data, ellertext/plain.- Anmodningen indeholder ingen brugerdefinerede headers (headers ud over standard HTTP-headers og CORS-specifikke headers).
Når en browser sender en simpel tværgående anmodning, tilføjer den automatisk en Origin-header, der angiver oprindelsen af den side, der foretager anmodningen. Serveren skal derefter inkludere en Access-Control-Allow-Origin-header i sit svar. Denne header skal matche den anmodende oprindelse eller være et wildcard (*).
Eksempel på simpel anmodning:
Browser Anmodning (fra https://frontend.example.com):
GET /data HTTP/1.1 Host: api.example.com Origin: https://frontend.example.com Server Svar:
HTTP/1.1 200 OK Access-Control-Allow-Origin: https://frontend.example.com Content-Type: application/json { "message": "Data fetched successfully" } Hvis Access-Control-Allow-Origin-headeren er til stede og matcher, eller hvis den er *, vil browseren tillade, at dataene bruges af frontend.
2. Preflighted Requests
Anmodninger, der ikke opfylder kriterierne for 'simple requests', betragtes som 'preflighted'. Dette inkluderer anmodninger, der:
- Bruger andre HTTP-metoder end
GET,HEADellerPOST(f.eks.PUT,DELETE). - Bruger
POSTmed enContent-Type, der ikke er tilladt for simple requests (f.eks.application/json). - Indeholder brugerdefinerede headers (f.eks.
Authorization,X-Custom-Header).
Før browseren sender en preflighted anmodning, sender den først en preflight OPTIONS-anmodning til serveren. Denne anmodning indeholder headers som Access-Control-Request-Method og Access-Control-Request-Headers, der angiver den faktiske anmodnings metode og headers.

Serveren skal svare på OPTIONS-anmodningen med relevante CORS-headers, herunder Access-Control-Allow-Origin, Access-Control-Allow-Methods og Access-Control-Allow-Headers. Hvis svaret indikerer, at den oprindelige anmodning er tilladt, sender browseren den faktiske anmodning. Ellers blokeres anmodningen.
Eksempel på preflighted anmodning:
Browser Anmodning (OPTIONS, fra https://frontend.example.com til POST /users med JSON):
OPTIONS /users HTTP/1.1 Host: api.example.com Origin: https://frontend.example.com Access-Control-Request-Method: POST Access-Control-Request-Headers: Content-Type, Authorization Server Svar:
HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://frontend.example.com Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: Content-Type, Authorization Hvis preflight-svaret er positivt, sender browseren den faktiske POST-anmodning.
Browser Anmodning (POST, fra https://frontend.example.com):
POST /users HTTP/1.1 Host: api.example.com Origin: https://frontend.example.com Content-Type: application/json Authorization: Bearer YOUR_TOKEN { "name": "John Doe", "email": "[email protected]" } Server Svar:
HTTP/1.1 201 Created Access-Control-Allow-Origin: https://frontend.example.com Content-Type: application/json { "id": 123, "message": "User created successfully" } Konfiguration af CORS i forskellige backend-frameworks
Implementeringen af CORS varierer afhængigt af det backend-framework, du bruger. Her er eksempler på populære teknologier:
Node.js (Express)
Den mest almindelige måde at håndtere CORS i Express er ved at bruge cors-middlewarepakken.

- Installation:
npm install cors - Konfiguration:
const express = require('express'); const cors = require('cors'); const app = express(); // Simpel konfiguration: Tillad alle oprindelser (kun til udvikling) // app.use(cors()); // Mere specifik konfiguration: const corsOptions = { origin: 'https://frontend.example.com', // Tillad kun denne oprindelse methods: ['GET', 'POST', 'PUT', 'DELETE'], // Tilladte metoder allowedHeaders: ['Content-Type', 'Authorization'], // Tilladte headers credentials: true // Tillad cookies og autentifikationsoplysninger }; app.use(cors(corsOptions)); app.get('/api/data', (req, res) => { res.json({ message: 'CORS er aktiveret!' }); }); app.listen(8080, () => { console.log('Server kører på port 8080'); });For at håndtere preflight-anmodninger automatisk, sikrer
cors-middleware, at OPTIONS-anmodninger besvares korrekt.
Python (Flask)
Flask-CORS-udvidelsen gør det nemt at konfigurere CORS.
- Installation:
pip install Flask-Cors - Konfiguration:
from flask import Flask, jsonify from flask_cors import CORS app = Flask(__name__) # Tillad CORS for alle ruter og alle oprindelser (ikke anbefalet til produktion) # CORS(app) # Specifik konfiguration: CORS(app, resources={ "/api/*": { "origins": "https://frontend.example.com", "methods": ["GET", "POST", "PUT", "DELETE"], "allow_headers": ["Content-Type", "Authorization"], "supports_credentials": True } }) @app.route('/api/data') def get_data(): return jsonify({'message': 'CORS er aktiveret i Flask!'}) if __name__ == '__main__': app.run(port=5000)Flask-CORS håndterer automatisk OPTIONS-anmodninger for de konfigurerede ruter.

Yes, if you are developing an API and want to make it public and want mobile users or other site consumers use it, you should set CORS for any site (*) , always. You can read more info here:
Java (Spring Boot)
I Spring Boot kan CORS konfigureres globalt eller på controller-niveau.
- Global konfiguration (anbefalet):
import org.springframework.context.annotation.Bean; 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 WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("https://frontend.example.com") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("Content-Type", "Authorization") .allowCredentials(true); } } - Controller-niveau konfiguration:
import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @RestController @CrossOrigin(origins = "https://frontend.example.com", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE}, allowedHeaders = {"Content-Type", "Authorization"}, allowCredentials = "true") public class ApiController { @GetMapping("/api/data") public ResponseEntity<String> getData() { return ResponseEntity.ok("CORS er aktiveret i Spring Boot!"); } }Spring Boot håndterer automatisk OPTIONS-anmodninger baseret på disse konfigurationer.
Almindelige CORS-fejl og løsninger
Her er nogle af de mest almindelige CORS-fejl og, hvordan man løser dem:
| Fejlbesked/Problem | Årsag | Løsning |
|---|---|---|
No 'Access-Control-Allow-Origin' header is present | Serveren sender ikke Access-Control-Allow-Origin-headeren, eller den matcher ikke den anmodende oprindelse. | Konfigurer serveren til at inkludere den korrekte Access-Control-Allow-Origin-header for den specifikke oprindelse eller brug wildcard * (med forsigtighed). |
Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers | Serveren tillader ikke den specifikke header, som browseren sender. | Tilføj den manglende header (f.eks. X-Requested-With) til allowedHeaders i CORS-konfigurationen. |
Method PUT is not allowed by Access-Control-Allow-Methods | Serveren tillader ikke den anvendte HTTP-metode (f.eks. PUT). | Tilføj den krævede metode (f.eks. PUT) til allowedMethods i CORS-konfigurationen. |
Fejl ved brug af Access-Control-Allow-Credentials: true og wildcard * | Specifikationen tillader ikke brug af wildcard (*) når Access-Control-Allow-Credentials er sat til true. | Angiv altid specifikke oprindelser, når du tillader credentials. Undgå Access-Control-Allow-Origin: * med allowCredentials: true. |
Preflight-anmodning fejler (OPTIONS-anmodning får 404 eller 405) | Serveren håndterer ikke OPTIONS-metoden korrekt, eller den mangler de nødvendige CORS-headers i OPTIONS-svaret. | Sørg for, at dit CORS-middleware eller din konfiguration korrekt håndterer OPTIONS-anmodninger og inkluderer de nødvendige Access-Control-*-headers. |
Bedste praksis for CORS-konfiguration
For at sikre robust og sikker kommunikation er her nogle bedste praksis:
- Begræns oprindelser: Undgå at bruge wildcard (
*) i produktion, især hvis din API håndterer følsomme data. Angiv altid specifikke, tilladte oprindelser. - Tillad kun nødvendige metoder og headers: Minimer angrebsfladen ved kun at tillade de HTTP-metoder og headers, som din applikation rent faktisk bruger.
- Håndter preflight-anmodninger korrekt: Sørg for, at din server altid svarer korrekt på
OPTIONS-anmodninger. - Brug
credentials: truemed forsigtighed: Hvis din API kræver cookies eller andre credentials, skal du tillade dem eksplicit og sikre, at oprindelsen er specifikt angivet. - Miljøbaseret konfiguration: Hav forskellige CORS-indstillinger for udviklings-, staging- og produktionsmiljøer.
- Overvågning: Log CORS-relaterede hændelser for at identificere og afhjælpe potentielle sikkerhedsproblemer eller konfigurationsfejl.
Konklusion
CORS er en uundværlig del af at bygge moderne, distribuerede webapplikationer, der involverer RESTful API'er. Ved at forstå Same-Origin Policy, hvordan CORS-mekanismen fungerer, og hvordan man korrekt konfigurerer CORS på tværs af forskellige backend-teknologier, kan udviklere sikre, at deres API'er er tilgængelige for de tilsigtede klienter, samtidig med at de opretholder et højt niveau af sikkerhed. Korrekt implementering af CORS er nøglen til en problemfri og sikker kommunikation mellem frontend og backend.
Hvis du vil læse andre artikler, der ligner Forstå CORS: Nøglen til RESTful API-kommunikation, kan du besøge kategorien Teknologi.
