Lås upp hemligheterna med CORS (Cross-Origin Resource Sharing) och lär dig hur du säkert aktiverar förfrågningar mellan domäner i dina webbapplikationer. Denna kompletta guide täcker allt från grunderna till avancerade konfigurationer, vilket säkerställer sömlös och säker kommunikation mellan olika ursprung.
CORS avmystifierat: En omfattande guide till Cross-Origin Resource Sharing
I dagens sammankopplade webb behöver applikationer ofta komma åt resurser från olika ursprung. Det är här Cross-Origin Resource Sharing (CORS) kommer in i bilden. CORS är en avgörande säkerhetsmekanism som styr hur webbläsare hanterar förfrågningar från ett ursprung (domän, protokoll och port) till ett annat. Att förstå CORS är avgörande för varje webbutvecklare för att bygga säkra och funktionella webbapplikationer.
Vad är Same-Origin Policy?
Innan vi dyker in i CORS är det viktigt att förstå Same-Origin Policy (SOP). SOP är en grundläggande säkerhetsmekanism som implementeras i webbläsare. Dess syfte är att förhindra skadliga skript på en webbplats från att komma åt känslig data på en annan webbplats. Ett ursprung definieras av kombinationen av protokoll (t.ex. HTTP eller HTTPS), domän (t.ex. example.com) och portnummer (t.ex. 80 eller 443). Två URL:er anses ha samma ursprung om de delar samma protokoll, domän och port.
Exempel:
http://example.com/app1
ochhttp://example.com/app2
- Samma ursprung (samma protokoll, domän och port)https://example.com/app1
ochhttp://example.com/app1
- Annat ursprung (annat protokoll)http://example.com:8080/app1
ochhttp://example.com/app1
- Annat ursprung (annan port)http://sub.example.com/app1
ochhttp://example.com/app1
- Annat ursprung (annan subdomän – anses vara annan domän)
SOP begränsar skript från att komma åt resurser från ett annat ursprung om inte specifika åtgärder, såsom CORS, finns på plats för att tillåta det.
Varför är CORS nödvändigt?
Även om Same-Origin Policy är avgörande för säkerheten, kan den också vara restriktiv. Många moderna webbapplikationer är beroende av att hämta data från olika servrar, som API:er eller content delivery networks (CDN). CORS erbjuder ett kontrollerat sätt att lätta på SOP och tillåta legitima förfrågningar mellan olika ursprung samtidigt som säkerheten upprätthålls.
Tänk dig ett scenario där en webbapplikation som ligger på http://example.com
behöver hämta data från en API-server på http://api.example.net
. Utan CORS skulle webbläsaren blockera denna förfrågan på grund av SOP. CORS tillåter API-servern att explicit specificera vilka ursprung som får komma åt dess resurser, vilket gör att webbapplikationen kan fungera korrekt.
Hur CORS fungerar: Grunderna
CORS fungerar genom en serie HTTP-rubriker som utbyts mellan klienten (webbläsaren) och servern. Servern använder dessa rubriker för att informera webbläsaren om den får tillgång till den begärda resursen. Den centrala HTTP-rubriken som är involverad är Access-Control-Allow-Origin
.
Scenario 1: Enkel förfrågan
En "enkel förfrågan" är en GET-, HEAD- eller POST-förfrågan som uppfyller specifika kriterier (t.ex. att Content-Type
-rubriken är en av application/x-www-form-urlencoded
, multipart/form-data
, eller text/plain
). I detta fall skickar webbläsaren förfrågan direkt till servern, och servern svarar med Access-Control-Allow-Origin
-rubriken.
Klientförfrågan (från http://example.com):
GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Serversvar (från http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"data": "Some data from the server"
}
I detta exempel svarar servern med Access-Control-Allow-Origin: http://example.com
, vilket indikerar att förfrågningar från http://example.com
är tillåtna. Om ursprunget i förfrågan inte matchar värdet i Access-Control-Allow-Origin
-rubriken (eller om rubriken inte finns), kommer webbläsaren att blockera svaret och förhindra klientsidans skript från att komma åt datan.
Scenario 2: Preflight-förfrågan (för komplexa förfrågningar)
För mer komplexa förfrågningar, som de som använder HTTP-metoder som PUT, DELETE, eller de med anpassade rubriker, utför webbläsaren en "preflight"-förfrågan med HTTP OPTIONS-metoden. Denna preflight-förfrågan frågar servern om tillstånd innan den faktiska förfrågan skickas. Servern svarar med rubriker som specificerar vilka metoder, rubriker och ursprung som är tillåtna.
Klientens preflight-förfrågan (från 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 (från 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
Förklaring av rubriker:
Access-Control-Allow-Origin: http://example.com
- Indikerar att förfrågningar frånhttp://example.com
är tillåtna.Access-Control-Allow-Methods: GET, PUT, DELETE
- Anger de HTTP-metoder som är tillåtna för förfrågningar mellan olika ursprung.Access-Control-Allow-Headers: X-Custom-Header, Content-Type
- Listar de tillåtna anpassade rubrikerna i den faktiska förfrågan.Access-Control-Max-Age: 3600
- Anger varaktigheten (i sekunder) som preflight-svaret kan cachas av webbläsaren. Detta hjälper till att minska antalet preflight-förfrågningar.
Om serverns preflight-svar indikerar att förfrågan är tillåten, fortsätter webbläsaren med den faktiska förfrågan. Annars blockerar webbläsaren förfrågan.
Klientens faktiska förfrågan (från 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": "Some data to be updated"
}
Serversvar (från http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"status": "Data updated successfully"
}
Vanliga CORS-rubriker
Här är en genomgång av de viktigaste CORS-rubrikerna du behöver förstå:
Access-Control-Allow-Origin
: Denna rubrik är den mest grundläggande. Den specificerar vilket/vilka ursprung som får komma åt resursen. Möjliga värden inkluderar:- Ett specifikt ursprung (t.ex.
http://example.com
). *
(wildcard): Detta tillåter förfrågningar från vilket som helst ursprung. Använd med försiktighet, eftersom det kan kompromettera säkerheten om känslig data är inblandad. Det bör generellt undvikas i produktionsmiljöer.
- Ett specifikt ursprung (t.ex.
Access-Control-Allow-Methods
: Denna rubrik specificerar de HTTP-metoder (t.ex. GET, POST, PUT, DELETE) som är tillåtna för förfrågningar mellan olika ursprung. Den används i preflight-svaret.Access-Control-Allow-Headers
: Denna rubrik listar de anpassade rubriker som är tillåtna i förfrågningar mellan olika ursprung. Den används också i preflight-svaret.Access-Control-Allow-Credentials
: Denna rubrik indikerar om servern tillåter att autentiseringsuppgifter (t.ex. cookies, auktoriseringsrubriker) inkluderas i förfrågningar mellan olika ursprung. Den bör sättas tilltrue
om du behöver skicka autentiseringsuppgifter. På klientsidan måste du också sättawithCredentials = true
på XMLHttpRequest-objektet.Access-Control-Expose-Headers
: Som standard exponerar webbläsare endast en begränsad uppsättning svarsrubriker (t.ex.Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
) för klientsidans skript. Om du vill exponera andra rubriker måste du lista dem iAccess-Control-Expose-Headers
-rubriken.Access-Control-Max-Age
: Denna rubrik specificerar den maximala tiden (i sekunder) som en webbläsare kan cacha preflight-förfrågan. Ett längre värde minskar antalet preflight-förfrågningar, vilket förbättrar prestandan.
CORS i olika serverspråk
Att implementera CORS innebär vanligtvis att konfigurera din serverapplikation för att skicka lämpliga CORS-rubriker. Här är exempel på hur man gör detta i olika språk och ramverk:
Node.js med Express
Du kan använda middleware-paketet cors
:
const express = require('express');
const cors = require('cors');
const app = express();
// Aktivera CORS för alla ursprung (ANVÄND MED FÖRSIKTIGHET I PRODUKTION)
app.use(cors());
// Alternativt, konfigurera CORS för specifika ursprung
// app.use(cors({
// origin: 'http://example.com'
// }));
app.get('/data', (req, res) => {
res.json({ message: 'Detta är CORS-aktiverat för alla ursprung!' });
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Python med Flask
Du kan använda tillägget Flask-CORS
:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# Alternativt, konfigurera CORS för specifika ursprung
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})
@app.route("/data")
def hello():
return {"message": "Detta är CORS-aktiverat för alla ursprung!"}
if __name__ == '__main__':
app.run(debug=True)
Java med Spring Boot
Du kan konfigurera CORS i din Spring Boot-applikation med hjälp av annoteringar eller konfigurationsklasser:
Med annoteringar:
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") // Tillåt förfrågningar från http://example.com
public class DataController {
@GetMapping("/data")
public String getData() {
return "Detta är CORS-aktiverat för http://example.com!";
}
}
Med 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") // Tillåt förfrågningar från http://example.com
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
}
PHP
"Detta är CORS-aktiverat för http://example.com!");
echo json_encode($data);
?>
CORS och säkerhetsaspekter
Även om CORS möjliggör förfrågningar mellan olika ursprung är det avgörande att implementera det på ett säkert sätt. Här är några viktiga överväganden:
- Undvik att använda
*
förAccess-Control-Allow-Origin
i produktion: Detta tillåter förfrågningar från vilket ursprung som helst, vilket kan vara en säkerhetsrisk. Specificera istället explicit de ursprung som får komma åt dina resurser. - Validera
Origin
-rubriken på serversidan: Även om du använder ett ramverk som hanterar CORS-konfiguration är det god praxis att valideraOrigin
-rubriken på serversidan för att säkerställa att förfrågan kommer från ett förväntat ursprung. - Var medveten om
Access-Control-Allow-Credentials
: Om du använder autentiseringsuppgifter (t.ex. cookies, auktoriseringsrubriker), se till att sättaAccess-Control-Allow-Credentials: true
på serversidan ochwithCredentials = true
på klientsidan. Var dock medveten om att det inte är tillåtet att användaAccess-Control-Allow-Origin: *
närAccess-Control-Allow-Credentials
är satt tilltrue
. Du måste explicit specificera de tillåtna ursprungen. - Konfigurera
Access-Control-Allow-Methods
ochAccess-Control-Allow-Headers
korrekt: Tillåt endast de HTTP-metoder och rubriker som är nödvändiga för att din applikation ska fungera. Detta hjälper till att minska attackytan. - Använd HTTPS: Använd alltid HTTPS för dina webbapplikationer och API:er för att skydda data under överföring.
Felsökning av CORS-problem
CORS-problem kan vara frustrerande att felsöka. Här är några vanliga problem och hur man löser dem:
- "No 'Access-Control-Allow-Origin' header is present on the requested resource": Detta är det vanligaste CORS-felet. Det betyder att servern inte skickar
Access-Control-Allow-Origin
-rubriken i sitt svar. Dubbelkolla din serverkonfiguration för att säkerställa att rubriken skickas korrekt. - "Response to preflight request doesn't pass access control check: It does not have HTTP ok status": Detta fel indikerar att preflight-förfrågan misslyckades. Detta kan hända om servern inte är konfigurerad för att hantera OPTIONS-förfrågningar eller om
Access-Control-Allow-Methods
- ellerAccess-Control-Allow-Headers
-rubrikerna inte är korrekt konfigurerade. - "The value of the 'Access-Control-Allow-Origin' header in the response is not equal to the origin in the request": Detta fel betyder att ursprunget i förfrågan inte matchar värdet i
Access-Control-Allow-Origin
-rubriken. Se till att servern skickar rätt ursprung i svaret. - Webbläsarcache: Ibland kan webbläsare cacha CORS-svar, vilket kan leda till oväntat beteende. Försök att rensa din webbläsarcache eller använda en annan webbläsare för att se om det löser problemet. Du kan också använda
Access-Control-Max-Age
-rubriken för att styra hur länge webbläsaren cachar preflight-svaret.
Felsökningsverktyg:
- Webbläsarens utvecklarverktyg: Använd webbläsarens utvecklarverktyg (vanligtvis F12) för att inspektera nätverksförfrågningar och svar. Leta efter CORS-relaterade rubriker och felmeddelanden.
- Online CORS-kontrollverktyg: Det finns onlineverktyg som kan hjälpa dig att testa din CORS-konfiguration. Dessa verktyg skickar en förfrågan till din server och analyserar svarsrubrikerna för att identifiera potentiella problem.
Avancerade CORS-scenarier
Även om de grundläggande CORS-koncepten är relativt enkla, finns det några mer avancerade scenarier att överväga:
- CORS med subdomäner: Om du behöver tillåta förfrågningar från flera subdomäner (t.ex.
app1.example.com
,app2.example.com
), kan du inte bara använda ett wildcard som*.example.com
iAccess-Control-Allow-Origin
-rubriken. Istället måste du dynamiskt genereraAccess-Control-Allow-Origin
-rubriken baserat påOrigin
-rubriken i förfrågan. Kom ihåg att validera ursprunget mot en vitlista över tillåtna subdomäner för att förhindra säkerhetssårbarheter. - CORS med flera ursprung: Om du behöver tillåta förfrågningar från flera specifika ursprung kan du inte specificera flera ursprung i
Access-Control-Allow-Origin
-rubriken (t.ex.Access-Control-Allow-Origin: http://example.com, http://another.com
är ogiltigt). Istället måste du dynamiskt genereraAccess-Control-Allow-Origin
-rubriken baserat påOrigin
-rubriken i förfrågan. - CORS och CDN:er: När du använder ett CDN för att servera ditt API måste du konfigurera CDN:et för att vidarebefordra
Origin
-rubriken till din ursprungsserver och för att cachaAccess-Control-Allow-Origin
-rubriken korrekt. Konsultera din CDN-leverantörs dokumentation för specifika instruktioner.
Bästa praxis för CORS
För att säkerställa en säker och effektiv CORS-implementering, följ dessa bästa praxis:
- Principen om minsta privilegium: Tillåt endast den minimala uppsättningen ursprung, metoder och rubriker som är nödvändiga för att din applikation ska fungera korrekt.
- Granska CORS-konfigurationen regelbundet: I takt med att din applikation utvecklas, granska regelbundet din CORS-konfiguration för att säkerställa att den fortfarande är lämplig och säker.
- Använd ett ramverk eller bibliotek: Utnyttja befintliga ramverk eller bibliotek som erbjuder inbyggt CORS-stöd. Detta kan förenkla implementeringen och minska risken för fel.
- Övervaka CORS-överträdelser: Implementera övervakning för att upptäcka och reagera på potentiella CORS-överträdelser.
- Håll dig uppdaterad: Håll dig uppdaterad med de senaste CORS-specifikationerna och säkerhetsrekommendationerna.
Slutsats
CORS är en kritisk säkerhetsmekanism som möjliggör kontrollerade förfrågningar mellan olika ursprung i webbapplikationer. Att förstå hur CORS fungerar och hur man konfigurerar det korrekt är avgörande för varje webbutvecklare. Genom att följa riktlinjerna och bästa praxis som beskrivs i denna omfattande guide kan du bygga säkra och funktionella webbapplikationer som sömlöst interagerar med resurser från olika ursprung.
Kom ihåg att alltid prioritera säkerhet och undvika alltför tillåtande CORS-konfigurationer. Genom att noggrant överväga säkerhetskonsekvenserna av dina CORS-inställningar kan du skydda dina applikationer och data från obehörig åtkomst.
Vi hoppas att den här guiden har hjälpt dig att avmystifiera CORS. Glad kodning!