Kattava opas CORS-mekanismin ymmärtämiseen ja käyttöönottoon turvallista JavaScript-kommunikointia varten eri verkkotunnusten välillä.
Cross-Origin-tietoturvan toteutus: JavaScript-kommunikoinnin parhaat käytännöt
Nykypäivän verkottuneessa maailmassa JavaScript-sovellusten on usein oltava vuorovaikutuksessa eri alkuperää (verkkotunnuksia, protokollia tai portteja) olevien resurssien kanssa. Tätä vuorovaikutusta säätelee selaimen Same-Origin-käytäntö (Same-Origin Policy), joka on kriittinen turvallisuusmekanismi. Sen tarkoituksena on estää haitallisia skriptejä pääsemästä käsiksi arkaluontoisiin tietoihin verkkotunnusten rajojen yli. Laillinen eri alkuperää olevien resurssien välinen kommunikointi on kuitenkin usein välttämätöntä. Tässä kohtaa Cross-Origin Resource Sharing (CORS) astuu kuvaan. Tämä artikkeli tarjoaa kattavan yleiskatsauksen CORS-mekanismista, sen toteutuksesta ja parhaista käytännöistä turvalliseen cross-origin-kommunikointiin JavaScriptissä.
Same-Origin-käytännön ymmärtäminen
Same-Origin-käytäntö (SOP) on web-selainten perustavanlaatuinen tietoturvakonsepti. Se rajoittaa yhdestä alkuperästä ajettavia skriptejä pääsemästä käsiksi eri alkuperästä tuleviin resursseihin. Alkuperä (origin) määritellään protokollan (esim. HTTP tai HTTPS), verkkotunnuksen nimen (esim. example.com) ja portin numeron (esim. 80 tai 443) yhdistelmällä. Kahdella URL-osoitteella on sama alkuperä vain, jos kaikki kolme komponenttia ovat täsmälleen samat.
Esimerkiksi:
http://www.example.comjahttp://www.example.com/path: Sama alkuperähttp://www.example.comjahttps://www.example.com: Eri alkuperä (eri protokolla)http://www.example.comjahttp://subdomain.example.com: Eri alkuperä (eri verkkotunnus)http://www.example.com:80jahttp://www.example.com:8080: Eri alkuperä (eri portti)
SOP on kriittinen puolustuskeino Cross-Site Scripting (XSS) -hyökkäyksiä vastaan, joissa verkkosivustolle syötetyt haitalliset skriptit voivat varastaa käyttäjätietoja tai suorittaa luvattomia toimia käyttäjän puolesta.
Mitä on Cross-Origin Resource Sharing (CORS)?
CORS on mekanismi, joka käyttää HTTP-otsakkeita salliakseen palvelimien ilmoittaa, mitkä alkuperät (verkkotunnukset, skeemat tai portit) saavat käyttää niiden resursseja. Se käytännössä höllentää Same-Origin-käytäntöä tietyille cross-origin-pyynnöille, mahdollistaen laillisen kommunikoinnin ja suojaten samalla haitallisilta hyökkäyksiltä.
CORS toimii lisäämällä uusia HTTP-otsakkeita, jotka määrittelevät sallitut alkuperät ja metodit (esim. GET, POST, PUT, DELETE), jotka ovat sallittuja cross-origin-pyynnöille. Kun selain tekee cross-origin-pyynnön, se lähettää pyynnön mukana Origin-otsakkeen. Palvelin vastaa Access-Control-Allow-Origin-otsakkeella, joka määrittelee sallitun alkuperän (tai sallitut alkuperät). Jos pyynnön alkuperä vastaa Access-Control-Allow-Origin-otsakkeen arvoa (tai jos arvo on *), selain sallii JavaScript-koodin pääsyn vastaukseen.
Miten CORS toimii: Yksityiskohtainen selitys
CORS-prosessi sisältää tyypillisesti kahdenlaisia pyyntöjä:
- Yksinkertaiset pyynnöt: Nämä ovat pyyntöjä, jotka täyttävät tietyt kriteerit. Jos pyyntö täyttää nämä ehdot, selain lähettää pyynnön suoraan.
- Esikyselypyynnöt: Nämä ovat monimutkaisempia pyyntöjä, jotka edellyttävät selaimen lähettävän ensin "esikysely" OPTIONS -pyynnön palvelimelle määrittääkseen, onko varsinaisen pyynnön lähettäminen turvallista.
1. Yksinkertaiset pyynnöt
Pyyntöä pidetään "yksinkertaisena", jos se täyttää kaikki seuraavat ehdot:
- Metodi on
GET,HEADtaiPOST. - Jos metodi on
POST,Content-Type-otsake on jokin seuraavista: application/x-www-form-urlencodedmultipart/form-datatext/plain- Mukautettuja otsakkeita ei ole asetettu.
Esimerkki yksinkertaisesta pyynnöstä:
GET /resource HTTP/1.1
Origin: http://www.example.com
Esimerkki palvelimen vastauksesta, joka sallii alkuperän:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://www.example.com
Content-Type: application/json
{
"data": "Some data"
}
Jos Access-Control-Allow-Origin-otsake on läsnä ja sen arvo vastaa pyynnön alkuperää tai on asetettu arvoon *, selain sallii skriptin pääsyn vastausdataan. Muussa tapauksessa selain estää pääsyn vastaukseen, ja konsoliin ilmestyy virheilmoitus.
2. Esikyselypyynnöt
Pyyntöä pidetään "esikyselypyyntönä" (preflighted), jos se ei täytä yksinkertaisen pyynnön kriteerejä. Tämä tapahtuu tyypillisesti, kun pyyntö käyttää eri HTTP-metodia (esim. PUT, DELETE), asettaa mukautettuja otsakkeita tai käyttää muuta Content-Type-arvoa kuin sallittuja arvoja.
Ennen varsinaisen pyynnön lähettämistä selain lähettää ensin palvelimelle OPTIONS-pyynnön. Tämä "esikysely"-pyyntö sisältää seuraavat otsakkeet:
Origin: Pyynnön tekevän sivun alkuperä.Access-Control-Request-Method: HTTP-metodi, jota käytetään varsinaisessa pyynnössä (esim.PUT,DELETE).Access-Control-Request-Headers: Pilkulla erotettu lista mukautetuista otsakkeista, jotka lähetetään varsinaisessa pyynnössä.
Esimerkki esikyselypyynnöstä:
OPTIONS /resource HTTP/1.1
Origin: http://www.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header, Content-Type
Palvelimen on vastattava OPTIONS-pyyntöön seuraavilla otsakkeilla:
Access-Control-Allow-Origin: Alkuperä, jolle pyynnön tekeminen on sallittu (tai*, jos kaikki alkuperät sallitaan).Access-Control-Allow-Methods: Pilkulla erotettu lista HTTP-metodeista, jotka ovat sallittuja cross-origin-pyynnöille (esim.GET,POST,PUT,DELETE).Access-Control-Allow-Headers: Pilkulla erotettu lista mukautetuista otsakkeista, joiden lähettäminen pyynnössä on sallittua.Access-Control-Max-Age: Aika sekunteina, jonka esikyselyvastaus voidaan tallentaa selaimen välimuistiin.
Esimerkki palvelimen vastauksesta esikyselypyyntöön:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header, Content-Type
Access-Control-Max-Age: 86400
Jos palvelimen vastaus esikyselypyyntöön osoittaa, että varsinainen pyyntö on sallittu, selain lähettää varsinaisen pyynnön. Muussa tapauksessa selain estää pyynnön ja näyttää virheilmoituksen.
CORS-toteutus palvelinpuolella
CORS toteutetaan pääasiassa palvelinpuolella asettamalla asianmukaiset HTTP-otsakkeet vastaukseen. Toteutuksen yksityiskohdat vaihtelevat käytetyn palvelinpuolen teknologian mukaan.
Esimerkki: Node.js ja Express:
const express = require('express');
const cors = require('cors');
const app = express();
// Enable CORS for all origins
app.use(cors());
// Alternatively, configure CORS for specific origins
// const corsOptions = {
// origin: 'http://www.example.com'
// };
// app.use(cors(corsOptions));
app.get('/resource', (req, res) => {
res.json({ message: 'This is a CORS-enabled resource' });
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
cors-middleware yksinkertaistaa CORS-otsakkeiden asettamista Expressissä. Voit sallia CORSin kaikille alkuperille käyttämällä cors() tai määrittää sen tietyille alkuperille käyttämällä cors(corsOptions).
Esimerkki: Python ja Flask:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route("/resource")
def hello():
return {"message": "This is a CORS-enabled resource"}
if __name__ == '__main__':
app.run(debug=True)
flask_cors-laajennus tarjoaa helpon tavan ottaa CORS käyttöön Flask-sovelluksissa. Voit sallia CORSin kaikille alkuperille antamalla app-olion CORS()-funktiolle. Myös määritykset tietyille alkuperille ovat mahdollisia.
Esimerkki: Java ja Spring Boot:
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("/resource")
.allowedOrigins("http://www.example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("Content-Type", "X-Custom-Header")
.allowCredentials(true)
.maxAge(3600);
}
}
Spring Bootissa voit määrittää CORSin käyttämällä WebMvcConfigurer-rajapintaa. Tämä mahdollistaa tarkan hallinnan sallituille alkuperille, metodeille, otsakkeille ja muille CORS-asetuksille.
CORS-otsakkeiden asettaminen suoraan (Yleinen esimerkki)
Jos et käytä mitään sovelluskehystä, voit asettaa otsakkeet suoraan palvelinpuolen koodissasi (esim. PHP, Ruby on Rails jne.):
CORSin parhaat käytännöt
Varmistaaksesi turvallisen ja tehokkaan cross-origin-kommunikoinnin, noudata näitä parhaita käytäntöjä:
- Vältä
Access-Control-Allow-Origin: *-määrityksen käyttöä tuotannossa: Kaikkien alkuperien salliminen päästä käsiksi resursseihisi voi olla tietoturvariski. Määritä sen sijaan tarkasti ne alkuperät, jotka ovat sallittuja. - Käytä HTTPS:ää: Käytä aina HTTPS:ää sekä pyynnön tekevässä että palvelevassa alkuperässä suojataksesi dataa siirron aikana.
- Validoi syötteet: Validoi ja puhdista aina cross-origin-pyynnöistä saatu data estääksesi injektiohyökkäykset.
- Toteuta asianmukainen todennus ja valtuutus: Varmista, että vain valtuutetut käyttäjät voivat käyttää arkaluontoisia resursseja.
- Välimuistita esikyselyvastaukset: Käytä
Access-Control-Max-Age-otsaketta esikyselyvastausten välimuistittamiseen jaOPTIONS-pyyntöjen määrän vähentämiseen. - Harkitse tunnisteiden (credentials) käyttöä: Jos API-rajapintasi vaatii todennusta evästeillä tai HTTP-todennuksella, sinun on asetettava palvelimella
Access-Control-Allow-Credentials-otsakkeen arvoksitrueja JavaScript-koodissasicredentials-asetuksen arvoksi'include'(esim. käyttäessäsifetch- taiXMLHttpRequest-rajapintaa). Ole erittäin varovainen tämän asetuksen kanssa, sillä se voi aiheuttaa tietoturvahaavoittuvuuksia, jos sitä ei käsitellä oikein. Lisäksi, kun Access-Control-Allow-Credentials on asetettu arvoon true, Access-Control-Allow-Origin ei voi olla "*". Sallittu alkuperä (tai sallitut alkuperät) on määriteltävä nimenomaisesti. - Tarkista ja päivitä CORS-määritykset säännöllisesti: Sovelluksesi kehittyessä tarkista ja päivitä CORS-määrityksesi säännöllisesti varmistaaksesi, että ne pysyvät turvallisina ja vastaavat tarpeitasi.
- Ymmärrä eri CORS-määritysten vaikutukset: Ole tietoinen eri CORS-määritysten tietoturvavaikutuksista ja valitse sovellukseesi sopiva määritys.
- Testaa CORS-toteutuksesi: Testaa CORS-toteutuksesi perusteellisesti varmistaaksesi, että se toimii odotetusti eikä aiheuta tietoturvahaavoittuvuuksia. Käytä selaimen kehittäjätyökaluja verkkopyyntöjen ja -vastausten tarkasteluun ja käytä automaattisia testaustyökaluja CORS-käyttäytymisen varmistamiseen.
Esimerkki: Fetch API:n käyttö CORSin kanssa
Tässä on esimerkki siitä, kuinka fetch-API:a käytetään cross-origin-pyynnön tekemiseen:
fetch('https://api.example.com/data', {
method: 'GET',
mode: 'cors', // Kertoo selaimelle, että tämä on CORS-pyyntö
headers: {
'Content-Type': 'application/json',
'X-Custom-Header': 'value'
}
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});
mode: 'cors' -asetus kertoo selaimelle, että kyseessä on CORS-pyyntö. Jos palvelin ei salli alkuperää, selain estää pääsyn vastaukseen ja aiheuttaa virheen.
Jos käytät tunnisteita (esim. evästeitä), sinun on asetettava credentials-asetuksen arvoksi 'include':
fetch('https://api.example.com/data', {
method: 'GET',
mode: 'cors',
credentials: 'include', // Sisällytä evästeet pyyntöön
headers: {
'Content-Type': 'application/json'
}
})
.then(response => {
// ...
});
CORS ja JSONP
JSON with Padding (JSONP) on vanhempi tekniikka Same-Origin-käytännön kiertämiseen. Se toimii luomalla dynaamisesti <script>-tagin, joka lataa dataa eri verkkotunnuksesta. Vaikka JSONP voi olla hyödyllinen tietyissä tilanteissa, sillä on merkittäviä tietoturvarajoituksia, ja sitä tulisi välttää, kun se on mahdollista. CORS on ensisijainen ratkaisu cross-origin-kommunikointiin, koska se tarjoaa turvallisemman ja joustavamman mekanismin.
Keskeiset erot CORSin ja JSONP:n välillä:
- Tietoturva: CORS on turvallisempi kuin JSONP, koska se antaa palvelimelle mahdollisuuden hallita, mitkä alkuperät saavat käyttää sen resursseja. JSONP ei tarjoa minkäänlaista alkuperän hallintaa.
- HTTP-metodit: CORS tukee kaikkia HTTP-metodeja (esim.
GET,POST,PUT,DELETE), kun taas JSONP tukee vainGET-pyyntöjä. - Virheiden käsittely: CORS tarjoaa paremman virheidenkäsittelyn kuin JSONP. Kun CORS-pyyntö epäonnistuu, selain antaa yksityiskohtaisia virheilmoituksia. JSONP:n virheidenkäsittely rajoittuu sen havaitsemiseen, latasiko skripti onnistuneesti.
CORS-ongelmien vianmääritys
CORS-ongelmien vianmääritys voi olla turhauttavaa. Tässä on joitakin yleisiä vianmääritysvinkkejä:
- Tarkista selaimen konsoli: Selaimen konsoli antaa yleensä yksityiskohtaisia virheilmoituksia CORS-ongelmista.
- Tarkastele verkkopyyntöjä: Käytä selaimen kehittäjätyökaluja tarkastellaksesi sekä pyynnön että vastauksen HTTP-otsakkeita. Varmista, että
Origin- jaAccess-Control-Allow-Origin-otsakkeet on asetettu oikein. - Varmista palvelinpuolen määritykset: Tarkista palvelinpuolen CORS-määritykset varmistaaksesi, että ne sallivat oikeat alkuperät, metodit ja otsakkeet.
- Tyhjennä selaimen välimuisti: Joskus välimuistiin tallennetut esikyselyvastaukset voivat aiheuttaa CORS-ongelmia. Kokeile tyhjentää selaimen välimuisti tai käyttää yksityistä selausikkunaa.
- Käytä CORS-välityspalvelinta: Joissakin tapauksissa saatat joutua käyttämään CORS-välityspalvelinta (proxy) CORS-rajoitusten kiertämiseen. Ole kuitenkin tietoinen siitä, että CORS-välityspalvelimen käyttö voi aiheuttaa tietoturvariskejä.
- Tarkista virheelliset määritykset: Etsi yleisiä virheellisiä määrityksiä, kuten puuttuva
Access-Control-Allow-Origin-otsake, virheellisetAccess-Control-Allow-Methods- taiAccess-Control-Allow-Headers-arvot tai virheellinenOrigin-otsake pyynnössä.
Yhteenveto
Cross-Origin Resource Sharing (CORS) on olennainen mekanismi turvallisen cross-origin-kommunikoinnin mahdollistamiseksi JavaScript-sovelluksissa. Ymmärtämällä Same-Origin-käytännön, CORS-työnkulun ja siihen liittyvät eri HTTP-otsakkeet, kehittäjät voivat toteuttaa CORSin tehokkaasti suojatakseen sovelluksiaan tietoturvahaavoittuvuuksilta ja sallien samalla lailliset cross-origin-pyynnöt. Parhaiden käytäntöjen noudattaminen CORS-määrityksissä ja toteutuksen säännöllinen tarkistaminen ovat ratkaisevan tärkeitä turvallisen ja vankkarakenteisen verkkosovelluksen ylläpitämisessä.
Tämä kattava opas tarjoaa vankan perustan CORSin ymmärtämiselle ja toteuttamiselle. Muista tutustua käyttämäsi palvelinpuolen teknologian viralliseen dokumentaatioon ja resursseihin varmistaaksesi, että toteutat CORSin oikein ja turvallisesti.