Paljasta CORSin (Cross-Origin Resource Sharing) salaisuudet ja opi mahdollistamaan verkkotunnusten väliset pyynnöt turvallisesti. Kattava opas kattaa kaiken perusteista edistyneisiin asetuksiin, varmistaen saumattoman ja turvallisen viestinnän.
CORSin mysteerit avattuna: Kattava opas Cross-Origin Resource Sharingiin
Nykypäivän verkottuneessa webissä sovellusten on usein käytettävä resursseja eri alkuperistä. Tässä Cross-Origin Resource Sharing (CORS) astuu kuvaan. CORS on olennainen turvallisuusmekanismi, joka säätelee, miten verkkoselaimet käsittelevät pyyntöjä yhdestä alkuperästä (verkkotunnus, protokolla ja portti) toiseen. CORSin ymmärtäminen on välttämätöntä jokaiselle web-kehittäjälle turvallisten ja toimivien verkkosovellusten rakentamiseksi.
Mikä on Same-Origin-käytäntö?
Ennen kuin sukellamme CORSiin, on tärkeää ymmärtää Same-Origin-käytäntö (SOP). SOP on verkkoselaimiin toteutettu perustavanlaatuinen turvallisuusmekanismi. Sen tarkoituksena on estää yhdellä verkkosivustolla olevia haitallisia skriptejä pääsemästä käsiksi arkaluontoisiin tietoihin toisella verkkosivustolla. Alkuperä (origin) määritellään protokollan (esim. HTTP tai HTTPS), verkkotunnuksen (esim. example.com) ja porttinumeron (esim. 80 tai 443) yhdistelmällä. Kahden URL-osoitteen katsotaan olevan samasta alkuperästä, jos niillä on sama protokolla, verkkotunnus ja portti.
Esimerkki:
http://example.com/app1
jahttp://example.com/app2
- Sama alkuperä (sama protokolla, verkkotunnus ja portti)https://example.com/app1
jahttp://example.com/app1
- Eri alkuperä (eri protokolla)http://example.com:8080/app1
jahttp://example.com/app1
- Eri alkuperä (eri portti)http://sub.example.com/app1
jahttp://example.com/app1
- Eri alkuperä (eri aliverkkotunnus – katsotaan eri verkkotunnukseksi)
SOP rajoittaa skriptien pääsyä eri alkuperästä peräisin oleviin resursseihin, ellei sen sallimiseksi ole käytössä erityisiä toimenpiteitä, kuten CORSia.
Miksi CORS on välttämätön?
Vaikka Same-Origin-käytäntö on elintärkeä turvallisuuden kannalta, se voi olla myös rajoittava. Monet nykyaikaiset verkkosovellukset tukeutuvat tietojen hakemiseen eri palvelimilta, kuten API-rajapinnoista tai sisällönjakeluverkoista (CDN). CORS tarjoaa hallitun tavan höllentää SOP-käytäntöä ja sallia lailliset alkuperien väliset pyynnöt turvallisuutta vaarantamatta.
Kuvitellaan tilanne, jossa osoitteessa http://example.com
isännöity verkkosovellus tarvitsee tietoja API-palvelimelta, joka sijaitsee osoitteessa http://api.example.net
. Ilman CORSia selain estäisi tämän pyynnön SOP-käytännön vuoksi. CORSin avulla API-palvelin voi nimenomaisesti määrittää, mitkä alkuperät saavat käyttää sen resursseja, mikä mahdollistaa verkkosovelluksen oikean toiminnan.
Miten CORS toimii: Perusteet
CORS toimii asiakkaan (selaimen) ja palvelimen välillä vaihdettavien HTTP-otsakkeiden avulla. Palvelin käyttää näitä otsakkeita ilmoittaakseen selaimelle, onko sillä lupa käyttää pyydettyä resurssia. Keskeisin HTTP-otsake on Access-Control-Allow-Origin
.
Skenaario 1: Yksinkertainen pyyntö
"Yksinkertainen pyyntö" on GET-, HEAD- tai POST-pyyntö, joka täyttää tietyt kriteerit (esim. Content-Type
-otsakkeen arvo on application/x-www-form-urlencoded
, multipart/form-data
tai text/plain
). Tässä tapauksessa selain lähettää pyynnön suoraan palvelimelle, ja palvelin vastaa Access-Control-Allow-Origin
-otsakkeella.
Asiakaspyyntö (osoitteesta http://example.com):
GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Palvelimen vastaus (osoitteesta http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"data": "Tietoa palvelimelta"
}
Tässä esimerkissä palvelin vastaa otsakkeella Access-Control-Allow-Origin: http://example.com
, mikä ilmaisee, että pyynnöt osoitteesta http://example.com
ovat sallittuja. Jos pyynnön alkuperä ei vastaa Access-Control-Allow-Origin
-otsakkeen arvoa (tai jos otsake puuttuu), selain estää vastauksen ja estää asiakaspuolen skriptiä pääsemästä käsiksi tietoihin.
Skenaario 2: Esikyselypyyntö (monimutkaisille pyynnöille)
Monimutkaisempien pyyntöjen, kuten PUT- tai DELETE-metodeja tai mukautettuja otsakkeita käyttävien pyyntöjen, kohdalla selain suorittaa "esikyselypyynnön" (preflight request) käyttämällä HTTP OPTIONS -metodia. Tämä esikyselypyyntö kysyy palvelimelta lupaa ennen varsinaisen pyynnön lähettämistä. Palvelin vastaa otsakkeilla, jotka määrittävät, mitkä metodit, otsakkeet ja alkuperät ovat sallittuja.
Asiakkaan esikyselypyyntö (osoitteesta 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
Palvelimen vastaus (osoitteesta 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
Otsakkeiden selitykset:
Access-Control-Allow-Origin: http://example.com
- Ilmaisee, että pyynnöt osoitteestahttp://example.com
ovat sallittuja.Access-Control-Allow-Methods: GET, PUT, DELETE
- Määrittää sallitut HTTP-metodit alkuperien välisille pyynnöille.Access-Control-Allow-Headers: X-Custom-Header, Content-Type
- Listaa sallitut mukautetut otsakkeet varsinaisessa pyynnössä.Access-Control-Max-Age: 3600
- Määrittää ajan (sekunneissa), jonka selain voi tallentaa esikyselyvastauksen välimuistiin. Tämä auttaa vähentämään esikyselypyyntöjen määrää.
Jos palvelimen esikyselyvastaus osoittaa pyynnön olevan sallittu, selain jatkaa varsinaisen pyynnön lähettämiseen. Muussa tapauksessa selain estää pyynnön.
Asiakkaan varsinainen pyyntö (osoitteesta http://example.com):
PUT /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
X-Custom-Header: jokin-arvo
Content-Type: application/json
{
"data": "Päivitettävää tietoa"
}
Palvelimen vastaus (osoitteesta http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"status": "Tiedot päivitetty onnistuneesti"
}
Yleiset CORS-otsakkeet
Tässä on erittely keskeisistä CORS-otsakkeista, jotka sinun tulee ymmärtää:
Access-Control-Allow-Origin
: Tämä on perustavanlaatuisin otsake. Se määrittää alkuperän/alkuperät, joilla on lupa käyttää resurssia. Mahdollisia arvoja ovat:- Tietty alkuperä (esim.
http://example.com
). *
(jokerimerkki): Tämä sallii pyynnöt mistä tahansa alkuperästä. Käytä varoen, koska se voi vaarantaa turvallisuuden, jos kyseessä on arkaluontoisia tietoja. Sitä tulisi yleensä välttää tuotantoympäristöissä.
- Tietty alkuperä (esim.
Access-Control-Allow-Methods
: Tämä otsake määrittää HTTP-metodit (esim. GET, POST, PUT, DELETE), jotka ovat sallittuja alkuperien välisissä pyynnöissä. Sitä käytetään esikyselyvastauksessa.Access-Control-Allow-Headers
: Tämä otsake listaa mukautetut otsakkeet, jotka ovat sallittuja alkuperien välisissä pyynnöissä. Sitä käytetään myös esikyselyvastauksessa.Access-Control-Allow-Credentials
: Tämä otsake ilmaisee, salliiko palvelin tunnisteiden (esim. evästeet, valtuutusotsakkeet) sisällyttämisen alkuperien välisiin pyyntöihin. Sen arvoksi tulee asettaatrue
, jos sinun tarvitsee lähettää tunnisteita. Asiakaspuolella sinun on myös asetettavawithCredentials = true
XMLHttpRequest-oliolle.Access-Control-Expose-Headers
: Oletuksena selaimet paljastavat asiakaspuolen skripteille vain rajoitetun joukon vastausotsakkeita (esim.Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
). Jos haluat paljastaa muita otsakkeita, sinun on listattava neAccess-Control-Expose-Headers
-otsakkeessa.Access-Control-Max-Age
: Tämä otsake määrittää enimmäisajan (sekunneissa), jonka selain voi tallentaa esikyselypyynnön välimuistiin. Pidempi arvo vähentää esikyselypyyntöjen määrää ja parantaa suorituskykyä.
CORS eri palvelinpuolen kielissä
CORSin toteuttaminen tarkoittaa tyypillisesti palvelinpuolen sovelluksen määrittämistä lähettämään asianmukaiset CORS-otsakkeet. Tässä on esimerkkejä siitä, miten tämä tehdään eri kielissä ja kehyksissä:
Node.js ja Express
Voit käyttää cors
-middleware-pakettia:
const express = require('express');
const cors = require('cors');
const app = express();
// Salli CORS kaikille alkuperille (KÄYTÄ VAROEN TUOTANNOSSA)
app.use(cors());
// Vaihtoehtoisesti määritä CORS tietyille alkuperille
// app.use(cors({
// origin: 'http://example.com'
// }));
app.get('/data', (req, res) => {
res.json({ message: 'Tämä on CORS-yhteensopiva kaikille alkuperille!' });
});
app.listen(3000, () => {
console.log('Palvelin käynnissä portissa 3000');
});
Python ja Flask
Voit käyttää Flask-CORS
-laajennusta:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# Vaihtoehtoisesti määritä CORS tietyille alkuperille
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})
@app.route("/data")
def hello():
return {"message": "Tämä on CORS-yhteensopiva kaikille alkuperille!"}
if __name__ == '__main__':
app.run(debug=True)
Java ja Spring Boot
Voit määrittää CORSin Spring Boot -sovelluksessasi annotaatioiden tai konfiguraatioluokkien avulla:
Käyttämällä annotaatioita:
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") // Salli pyynnöt osoitteesta http://example.com
public class DataController {
@GetMapping("/data")
public String getData() {
return "Tämä on CORS-yhteensopiva osoitteelle http://example.com!";
}
}
Käyttämällä konfiguraatiota:
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") // Salli pyynnöt osoitteesta http://example.com
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
}
PHP
"Tämä on CORS-yhteensopiva osoitteelle http://example.com!");
echo json_encode($data);
?>
CORS ja turvallisuusnäkökohdat
Vaikka CORS mahdollistaa alkuperien väliset pyynnöt, on tärkeää toteuttaa se turvallisesti. Tässä on joitain tärkeitä näkökohtia:
- Vältä
*
-merkin käyttöäAccess-Control-Allow-Origin
-otsakkeessa tuotannossa: Tämä sallii pyynnöt mistä tahansa alkuperästä, mikä voi olla turvallisuusriski. Määritä sen sijaan nimenomaisesti ne alkuperät, joilla on lupa käyttää resurssejasi. - Validoi
Origin
-otsake palvelinpuolella: Vaikka käyttäisit kehystä, joka hoitaa CORS-määritykset, on hyvä käytäntö validoidaOrigin
-otsake palvelinpuolella varmistaaksesi, että pyyntö tulee odotetusta alkuperästä. - Ole tietoinen
Access-Control-Allow-Credentials
-asetuksesta: Jos käytät tunnisteita (esim. evästeitä, valtuutusotsakkeita), varmista, että asetatAccess-Control-Allow-Credentials: true
palvelinpuolella jawithCredentials = true
asiakaspuolella. Huomaa kuitenkin, ettäAccess-Control-Allow-Origin: *
-arvon käyttö ei ole sallittua, kunAccess-Control-Allow-Credentials
on asetettu arvoontrue
. Sinun on määritettävä sallitut alkuperät nimenomaisesti. - Määritä
Access-Control-Allow-Methods
jaAccess-Control-Allow-Headers
oikein: Salli vain ne HTTP-metodit ja otsakkeet, jotka ovat välttämättömiä sovelluksesi toiminnalle. Tämä auttaa pienentämään hyökkäyspinta-alaa. - Käytä HTTPS:ää: Käytä aina HTTPS:ää verkkosovelluksissasi ja API-rajapinnoissasi suojataksesi tietoja siirron aikana.
CORS-ongelmien vianmääritys
CORS-ongelmien virheenkorjaus voi olla turhauttavaa. Tässä on joitain yleisiä ongelmia ja niiden ratkaisuja:
- "No 'Access-Control-Allow-Origin' header is present on the requested resource": Tämä on yleisin CORS-virhe. Se tarkoittaa, että palvelin ei lähetä
Access-Control-Allow-Origin
-otsaketta vastauksessaan. Tarkista palvelinpuolen määritykset varmistaaksesi, että otsake lähetetään oikein. - "Response to preflight request doesn't pass access control check: It does not have HTTP ok status": Tämä virhe osoittaa, että esikyselypyyntö epäonnistui. Tämä voi johtua siitä, että palvelinta ei ole määritetty käsittelemään OPTIONS-pyyntöjä tai että
Access-Control-Allow-Methods
- taiAccess-Control-Allow-Headers
-otsakkeita ei ole määritetty oikein. - "The value of the 'Access-Control-Allow-Origin' header in the response is not equal to the origin in the request": Tämä virhe tarkoittaa, että pyynnön alkuperä ei vastaa
Access-Control-Allow-Origin
-otsakkeen arvoa. Varmista, että palvelin lähettää vastauksessa oikean alkuperän. - Selaimen välimuisti: Joskus selaimet voivat tallentaa CORS-vastauksia välimuistiin, mikä voi johtaa odottamattomaan käytökseen. Kokeile tyhjentää selaimen välimuisti tai käyttää toista selainta nähdäksesi, ratkaiseeko se ongelman. Voit myös käyttää
Access-Control-Max-Age
-otsaketta hallitaksesi, kuinka kauan selain tallentaa esikyselyvastauksen välimuistiin.
Vianmääritystyökalut:
- Selaimen kehittäjätyökalut: Käytä selaimen kehittäjätyökaluja (yleensä F12-näppäimellä) tarkastellaksesi verkkopyyntöjä ja -vastauksia. Etsi CORSiin liittyviä otsakkeita ja virheilmoituksia.
- Online CORS-tarkistimet: On olemassa verkkotyökaluja, jotka voivat auttaa sinua testaamaan CORS-määrityksesi. Nämä työkalut lähettävät pyynnön palvelimellesi ja analysoivat vastausotsakkeet mahdollisten ongelmien tunnistamiseksi.
Edistyneet CORS-skenaariot
Vaikka CORSin peruskäsitteet ovat suhteellisen yksinkertaisia, on olemassa joitain edistyneempiä skenaarioita, jotka on otettava huomioon:
- CORS aliverkkotunnusten kanssa: Jos sinun on sallittava pyynnöt useista aliverkkotunnuksista (esim.
app1.example.com
,app2.example.com
), et voi yksinkertaisesti käyttää jokerimerkkiä kuten*.example.com
Access-Control-Allow-Origin
-otsakkeessa. Sen sijaan sinun on dynaamisesti generoitavaAccess-Control-Allow-Origin
-otsake pyynnönOrigin
-otsakkeen perusteella. Muista validoida alkuperä sallittujen aliverkkotunnusten valkoista listaa vastaan turvallisuushaavoittuvuuksien estämiseksi. - CORS useiden alkuperien kanssa: Jos sinun on sallittava pyynnöt useista tietyistä alkuperistä, et voi määrittää useita alkuperiä
Access-Control-Allow-Origin
-otsakkeessa (esim.Access-Control-Allow-Origin: http://example.com, http://another.com
on virheellinen). Sen sijaan sinun on dynaamisesti generoitavaAccess-Control-Allow-Origin
-otsake pyynnönOrigin
-otsakkeen perusteella. - CORS ja CDN:t: Kun käytät CDN:ää API:n tarjoamiseen, sinun on määritettävä CDN välittämään
Origin
-otsake alkuperäiselle palvelimellesi ja tallentamaanAccess-Control-Allow-Origin
-otsake oikein välimuistiin. Katso tarkemmat ohjeet CDN-palveluntarjoajasi dokumentaatiosta.
CORSin parhaat käytännöt
Varmistaaksesi turvallisen ja tehokkaan CORS-toteutuksen, noudata näitä parhaita käytäntöjä:
- Vähimpien oikeuksien periaate: Salli vain pienin mahdollinen joukko alkuperiä, metodeja ja otsakkeita, jotka ovat välttämättömiä sovelluksesi toiminnalle.
- Tarkista CORS-määritykset säännöllisesti: Kun sovelluksesi kehittyy, tarkista säännöllisesti CORS-määrityksesi varmistaaksesi, että ne ovat edelleen asianmukaiset ja turvalliset.
- Käytä kehystä tai kirjastoa: Hyödynnä olemassa olevia kehyksiä tai kirjastoja, jotka tarjoavat sisäänrakennetun CORS-tuen. Tämä voi yksinkertaistaa toteutusta ja vähentää virheiden riskiä.
- Seuraa CORS-rikkomuksia: Toteuta valvonta mahdollisten CORS-rikkomusten havaitsemiseksi ja niihin reagoimiseksi.
- Pysy ajan tasalla: Pysy ajan tasalla uusimmista CORS-määrityksistä ja turvallisuussuosituksista.
Johtopäätös
CORS on kriittinen turvallisuusmekanismi, joka mahdollistaa hallitut alkuperien väliset pyynnöt verkkosovelluksissa. CORSin toiminnan ja sen oikean määrittämisen ymmärtäminen on välttämätöntä jokaiselle web-kehittäjälle. Noudattamalla tässä kattavassa oppaassa esitettyjä ohjeita ja parhaita käytäntöjä voit rakentaa turvallisia ja toimivia verkkosovelluksia, jotka ovat saumattomasti vuorovaikutuksessa eri alkuperistä peräisin olevien resurssien kanssa.
Muista aina asettaa turvallisuus etusijalle ja välttää liian sallivien CORS-määritysten käyttöä. Harkitsemalla huolellisesti CORS-asetustesi turvallisuusvaikutuksia voit suojata sovelluksesi ja tietosi luvattomalta käytöltä.
Toivomme, että tämä opas on auttanut sinua avaamaan CORSin mysteereitä. Hyvää koodausta!