Perusteellinen tutkimus Cross-Origin Resource Sharing (CORS) ja esitarkistuspyynnöistä. Opi käsittelemään CORS-ongelmia ja suojaamaan web-sovelluksesi globaalille yleisölle.
CORS:n demystifiointi: Syvällinen perehtyminen JavaScript-esitarkistuspyyntöjen käsittelyyn
Web-kehityksen jatkuvasti laajenevassa maailmassa turvallisuus on ensiarvoisen tärkeää. Cross-Origin Resource Sharing (CORS) on keskeinen turvallisuusmekanismi, jonka verkkoselaimet toteuttavat rajoittaakseen verkkosivujen tekemistä pyyntöjä toiselle verkkotunnukselle kuin se, joka on palvellut verkkosivua. Tämä on perustavanlaatuinen turvallisuusominaisuus, joka on suunniteltu estämään haitallisia verkkosivuja pääsemästä käsiksi arkaluontoisiin tietoihin. Tämä kattava opas perehtyy CORS:n monimutkaisuuksiin keskittyen erityisesti esitarkistuspyyntöjen käsittelyyn. Tutkimme CORS:n "miksi", "mitä" ja "miten" tarjoten käytännön esimerkkejä ja ratkaisuja yleisiin ongelmiin, joita kehittäjät kohtaavat maailmanlaajuisesti.
Same-Origin-käytännön ymmärtäminen
CORS:n ytimessä on Same-Origin-käytäntö (SOP). Tämä käytäntö on selaimen tason turvallisuusmekanismi, joka rajoittaa yhdeltä originilta (lähteeltä) käynnissä olevia komentosarjoja pääsemästä käsiksi resurssiin eri originilta. Origin määritellään protokollan (esim. HTTP tai HTTPS), verkkotunnuksen (esim. example.com) ja portin (esim. 80 tai 443) mukaan. Kahdella URL-osoitteella on sama origin, jos nämä kolme osaa vastaavat täsmälleen.
Esimerkiksi:
https://www.example.com/app1/index.htmljahttps://www.example.com/app2/index.htmlovat sama origin (sama protokolla, verkkotunnus ja portti).https://www.example.com/index.htmljahttp://www.example.com/index.htmlovat eri originit (eri protokollat).https://www.example.com/index.htmljahttps://api.example.com/index.htmlovat eri originit (eri aliverkkotunnuksia pidetään eri verkkotunnuksina).https://www.example.com:8080/index.htmljahttps://www.example.com/index.htmlovat eri originit (eri portit).
SOP on suunniteltu estämään haitallisia komentosarjoja toisella verkkosivustolla pääsemästä käsiksi arkaluontoisiin tietoihin, kuten evästeisiin tai käyttäjän todennustietoihin, toisella verkkosivustolla. Vaikka SOP on olennainen turvallisuuden kannalta, se voi olla myös rajoittava, erityisesti silloin, kun tarvitaan laillisia cross-origin-pyyntöjä.
Mikä on Cross-Origin Resource Sharing (CORS)?
CORS on mekanismi, jonka avulla palvelimet voivat määrittää, mitkä originit (verkkotunnukset, skeemat tai portit) saavat käyttää niiden resursseja. Se olennaisesti löysentää SOP:tä ja mahdollistaa hallitun cross-origin-käytön. CORS toteutetaan käyttämällä HTTP-otsikoita, jotka vaihdetaan asiakkaan (tyypillisesti verkkoselain) ja palvelimen välillä.
Kun selain tekee cross-origin-pyynnön (ts. pyynnön eri originille kuin nykyinen sivu), se tarkistaa ensin, salliko palvelin pyynnön. Tämä tehdään tarkastelemalla Access-Control-Allow-Origin -otsikkoa palvelimen vastauksessa. Jos pyynnön origin on lueteltu tässä otsikossa (tai jos otsikoksi on asetettu *, mikä sallii kaikki originit), selain sallii pyynnön jatkaa. Muuten selain estää pyynnön estäen JavaScript-koodia pääsemästä käsiksi vastaustietoihin.
Esitarkistuspyyntöjen rooli
Tietyntyyppisten cross-origin-pyyntöjen osalta selain käynnistää esitarkistuspyynnön. Tämä on OPTIONS-pyyntö, joka lähetetään palvelimelle ennen varsinaista pyyntöä. Esitarkistuspyynnön tarkoituksena on määrittää, onko palvelin valmis hyväksymään varsinaisen pyynnön. Palvelin vastaa esitarkistuspyyntöön tiedoilla sallituista metodeista, otsikoista ja muista rajoituksista.
Esitarkistuspyynnöt käynnistyvät, kun cross-origin-pyyntö täyttää jonkin seuraavista ehdoista:
- Pyyntömetodi ei ole
GET,HEADtaiPOST. - Pyyntö sisältää mukautettuja otsikoita (ts. muita otsikoita kuin selaimen automaattisesti lisäämät).
Content-Type-otsikoksi on asetettu jokin muu kuinapplication/x-www-form-urlencoded,multipart/form-datataitext/plain.- Pyyntö käyttää
ReadableStream-objekteja rungossa.
Esimerkiksi PUT-pyyntö, jonka Content-Type on application/json, käynnistää esitarkistuspyynnön, koska se käyttää eri metodia kuin sallitut ja mahdollisesti kiellettyä sisältötyyppiä.
Miksi esitarkistuspyyntöjä?
Esitarkistuspyynnöt ovat olennaisia turvallisuuden kannalta, koska ne tarjoavat palvelimelle mahdollisuuden hylätä mahdollisesti vahingollisia cross-origin-pyyntöjä ennen kuin ne suoritetaan. Ilman esitarkistuspyyntöjä haitallinen verkkosivusto voisi mahdollisesti lähettää mielivaltaisia pyyntöjä palvelimelle ilman palvelimen nimenomaista suostumusta. Esitarkistuspyyntö antaa palvelimelle mahdollisuuden tarkistaa, että pyyntö on hyväksyttävä, ja estää mahdollisesti vahingollisia toimintoja.
Esitarkistuspyyntöjen käsittely palvelinpäässä
Esitarkistuspyyntöjen oikea käsittely on ratkaisevan tärkeää sen varmistamiseksi, että web-sovelluksesi toimii oikein ja turvallisesti. Palvelimen on vastattava OPTIONS-pyyntöön sopivilla CORS-otsikoilla osoittaakseen, onko varsinainen pyyntö sallittu.
Tässä on erittely keskeisistä CORS-otsikoista, joita käytetään esitarkistusvastauksissa:
Access-Control-Allow-Origin: Tämä otsikko määrittää originit, joilla on lupa käyttää resurssia. Se voidaan asettaa tietylle originille (esim.https://www.example.com) tai*:lle sallimaan kaikki originit. Kuitenkin*:n käyttöä ei yleensä suositella turvallisuussyistä, erityisesti jos palvelin käsittelee arkaluontoisia tietoja.Access-Control-Allow-Methods: Tämä otsikko määrittää HTTP-metodit, jotka sallitaan cross-origin-pyynnössä (esim.GET,POST,PUT,DELETE).Access-Control-Allow-Headers: Tämä otsikko määrittää luettelon ei-standardeista HTTP-otsikoista, jotka sallitaan varsinaisessa pyynnössä. Tämä on tarpeellista, jos asiakas lähettää mukautettuja otsikoita, kutenX-Custom-HeadertaiAuthorization.Access-Control-Allow-Credentials: Tämä otsikko ilmaisee, voiko varsinainen pyyntö sisältää tunnisteita, kuten evästeitä tai todennusotsikoita. Se on asetettavatrue:ksi, jos asiakaspuolen koodi lähettää tunnisteita ja palvelimen pitäisi hyväksyä ne. Huomautus: kun tämä otsikko on asetettu arvoon `true`, `Access-Control-Allow-Origin` *ei* voi olla asetettu arvoon `*`. Sinun on määritettävä origin.Access-Control-Max-Age: Tämä otsikko määrittää enimmäisajan (sekunteina), jonka selain voi välimuistiin tallentaa esitarkistusvastauksen. Tämä voi auttaa parantamaan suorituskykyä vähentämällä lähetettävien esitarkistuspyyntöjen määrää.
Esimerkki: Esitarkistuspyyntöjen käsittely Node.js:ssä Expressin avulla
Tässä on esimerkki siitä, miten esitarkistuspyyntöjä käsitellään Node.js-sovelluksessa Express-kehyksen avulla:
const express = require('express');
const cors = require('cors');
const app = express();
// Ota CORS käyttöön kaikille origineille (vain kehitystarkoituksiin!)
// Tuotannossa määritä sallitut originit paremman turvallisuuden vuoksi.
app.use(cors()); //tai app.use(cors({origin: 'https://www.example.com'}));
// Reitti OPTIONS-pyyntöjen (esitarkistus) käsittelyyn
app.options('/data', cors()); // Ota CORS käyttöön yhdelle reitille. Tai määritä origin: cors({origin: 'https://www.example.com'})
// Reitti GET-pyyntöjen käsittelyyn
app.get('/data', (req, res) => {
res.json({ message: 'Tämä on cross-origin-dataa!' });
});
// Reitti esitarkistuksen ja post-pyynnön käsittelyyn
app.options('/resource', cors()); // ota esitarkistuspyyntö käyttöön DELETE-pyynnölle
app.delete('/resource', cors(), (req, res, next) => {
res.send('delete resource')
})
const port = 3000;
app.listen(port, () => {
console.log(`Palvelin kuuntelee portissa ${port}`);
});
Tässä esimerkissä käytämme cors-middlewareä CORS-pyyntöjen käsittelyyn. Tarkempaa hallintaa varten CORS voidaan ottaa käyttöön reittikohtaisesti. Huomautus: tuotannossa on erittäin suositeltavaa määrittää sallitut originit origin-asetuksella sen sijaan, että sallittaisiin kaikki originit. Kaikkien originien salliminen käyttämällä * voi altistaa sovelluksesi turvallisuushaavoittuvuuksille.
Esimerkki: Esitarkistuspyyntöjen käsittely Pythonissa Flaskin avulla
Tässä on esimerkki siitä, miten esitarkistuspyyntöjä käsitellään Python-sovelluksessa Flask-kehyksen ja flask_cors-laajennuksen avulla:
from flask import Flask, jsonify
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app) # Ota CORS käyttöön kaikille reiteille
@app.route('/data')
@cross_origin()
def get_data():
data = {"message": "Tämä on cross-origin-dataa!"}
return jsonify(data)
if __name__ == '__main__':
app.run(debug=True)
Tämä on yksinkertaisin käyttö. Kuten aiemmin, originit voidaan rajoittaa. Katso lisätietoja flask-cors -dokumentaatiosta.
Esimerkki: Esitarkistuspyyntöjen käsittely Javassa Spring Bootin avulla
Tässä on esimerkki siitä, miten esitarkistuspyyntöjä käsitellään Java-sovelluksessa Spring Bootin avulla:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@SpringBootApplication
public class CorsApplication {
public static void main(String[] args) {
SpringApplication.run(CorsApplication.class, args);
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/data").allowedOrigins("http://localhost:8080");
}
};
}
}
Ja vastaava ohjain:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DataController {
@GetMapping("/data")
public String getData() {
return "Tämä on cross-origin-dataa!";
}
}
Yleiset CORS-ongelmat ja ratkaisut
Huolimatta sen tärkeydestä CORS voi usein olla kehittäjien turhautumisen lähde. Tässä on joitain yleisiä CORS-ongelmia ja niiden ratkaisuja:
-
Virhe: "Resurssissa ei ole 'Access-Control-Allow-Origin'-otsikkoa."
Tämä virhe osoittaa, että palvelin ei palauta
Access-Control-Allow-Origin-otsikkoa vastauksessaan. Korjataksesi tämän, varmista, että palvelin on määritetty sisältämään otsikon ja että se on asetettu oikealle originille tai*:lle (tarvittaessa).Ratkaisu: Määritä palvelin sisältämään `Access-Control-Allow-Origin` -otsikko vastauksessaan ja aseta se pyytävän verkkosivuston originille tai `*`:lle sallimaan kaikki originit (käytä varoen).
-
Virhe: "Esitarkistuspyynnön vastaus ei läpäise pääsynhallintatarkistusta: Pyyntöotsakekenttä X-Custom-Header ei ole sallittu Access-Control-Allow-Headers:lla esitarkistusvastauksessa."
Tämä virhe osoittaa, että palvelin ei salli mukautettua otsikkoa (
X-Custom-Headertässä esimerkissä) cross-origin-pyynnössä. Korjataksesi tämän, varmista, että palvelin sisällyttää otsikonAccess-Control-Allow-Headers-otsikkoon esitarkistusvastauksessa.Ratkaisu: Lisää mukautettu otsikko (esim. `X-Custom-Header`) palvelimen esitarkistusvastauksen `Access-Control-Allow-Headers` -otsikkoon.
-
Virhe: "Tunnistelipun arvo on 'true', mutta 'Access-Control-Allow-Origin'-otsikon arvo on '*'."
Kun
Access-Control-Allow-Credentials-otsikko on asetettu arvoontrue,Access-Control-Allow-Origin-otsikko on asetettava tietylle originille, ei*:lle. Tämä johtuu siitä, että tunnistetietojen salliminen kaikista origineista olisi turvallisuusriski.Ratkaisu: Kun käytät tunnistetietoja, aseta `Access-Control-Allow-Origin` tietylle originille `*`:n sijaan.
-
Esitarkistuspyyntöä ei lähetetä.
Tarkista uudelleen, että JavaScript-koodisi sisältää ominaisuuden `credentials: 'include'`. Tarkista myös, että palvelimesi sallii `Access-Control-Allow-Credentials: true`.
-
Palvelimen ja asiakkaan välillä on ristiriitaisia konfiguraatioita.
Tarkista huolellisesti palvelinpuolen CORS-konfiguraatiosi yhdessä asiakaspuolen asetusten kanssa. Väärät sovitukset (esim. palvelin sallii vain GET-pyynnöt, mutta asiakas lähettää POST-pyyntöjä) aiheuttavat CORS-virheitä.
CORS ja turvallisuuden parhaat käytännöt
Vaikka CORS mahdollistaa hallitun cross-origin-pääsyn, on olennaista noudattaa turvallisuuden parhaita käytäntöjä haavoittuvuuksien estämiseksi:
- Vältä
*:n käyttöäAccess-Control-Allow-Origin-otsikossa tuotannossa. Tämä sallii kaikkien originien pääsyn resursseihisi, mikä voi olla turvallisuusriski. Sen sijaan määritä tarkat originit, jotka ovat sallittuja. - Harkitse huolellisesti, mitkä metodit ja otsikot sallitaan. Sallita vain metodit ja otsikot, jotka ovat ehdottomasti tarpeellisia sovelluksesi oikealle toiminnolle.
- Toteuta asianmukaiset todennus- ja valtuutusmekanismit. CORS ei korvaa todennusta ja valtuutusta. Varmista, että API:si on suojattu asianmukaisilla turvatoimilla.
- Tarkista ja puhdista kaikki käyttäjän syötteet. Tämä auttaa estämään cross-site scripting (XSS) -hyökkäykset ja muut haavoittuvuudet.
- Pidä palvelinpuolen CORS-konfiguraatiosi ajan tasalla. Tarkista ja päivitä säännöllisesti CORS-konfiguraatiosi varmistaaksesi, että se vastaa sovelluksesi turvallisuusvaatimuksia.
CORS eri kehitysympäristöissä
CORS-ongelmat voivat ilmetä eri tavoin eri kehitysympäristöissä ja teknologioissa. Tässä on katsaus siihen, miten CORS:ia lähestytään muutamassa yleisessä skenaariossa:
Paikalliset kehitysympäristöt
Paikallisen kehityksen aikana CORS-ongelmat voivat olla erityisen ärsyttäviä. Selaimet estävät usein pyynnöt paikalliselta kehityspalvelimeltasi (esim. localhost:3000) etä-API:lle. Useat tekniikat voivat helpottaa tätä tuskaa:
- Selaimen laajennukset: Laajennukset, kuten "Allow CORS: Access-Control-Allow-Origin", voivat tilapäisesti poistaa CORS-rajoitukset testaustarkoituksiin. Älä kuitenkaan koskaan käytä niitä tuotannossa.
- Välityspalvelimet: Määritä välityspalvelin, joka välittää pyynnöt paikalliselta kehityspalvelimeltasi etä-API:lle. Tämä tekee pyynnöistä tehokkaasti "same-origin" selaimen näkökulmasta. Työkalut, kuten
http-proxy-middleware(Node.js:lle), ovat hyödyllisiä tähän. - Määritä palvelimen CORS: Jopa kehityksen aikana on parasta käytäntöä määrittää API-palvelimesi nimenomaisesti sallimaan pyynnöt paikalliselta kehitysoriginiltasi (esim.
http://localhost:3000). Tämä simuloi todellista CORS-konfiguraatiota ja auttaa sinua havaitsemaan ongelmat varhain.
Serverless-ympäristöt (esim. AWS Lambda, Google Cloud Functions)
Serverless-toiminnot edellyttävät usein huolellista CORS-konfiguraatiota. Monet serverless-alustat tarjoavat sisäänrakennetun CORS-tuen, mutta on ratkaisevan tärkeää määrittää se oikein:
- Alustakohtaiset asetukset: Käytä alustan sisäänrakennettuja CORS-konfigurointivaihtoehtoja. AWS Lambda esimerkiksi antaa sinun määrittää sallitut originit, metodit ja otsikot suoraan API Gateway -asetuksissa.
- Middleware/Kirjastot: Paremman joustavuuden saavuttamiseksi voit käyttää middlewareä tai kirjastoja CORS:n käsittelyyn serverless-funktion koodissa. Tämä on samankaltainen kuin lähestymistavat, joita käytetään perinteisissä palvelinympäristöissä (esim. `cors`-paketin käyttö Node.js Lambda -funktioissa).
- Harkitse
OPTIONS-metodia: Varmista, että serverless-funktiosi käsitteleeOPTIONS-pyynnöt oikein. Tämä sisältää usein erillisen reitin luomisen, joka palauttaa sopivat CORS-otsikot.
Mobiilisovellusten kehittäminen (esim. React Native, Flutter)
CORS on vähemmän suora huolenaihe natiivisovelluksille (Android, iOS), koska ne eivät tyypillisesti vahvista samaa alkuperäispolitiikkaa samalla tavalla kuin verkkoselaimet. CORS voi kuitenkin olla edelleen relevantti, jos mobiilisovelluksesi käyttää verkkonäkymää web-sisällön näyttämiseen tai jos käytät kehyksiä, kuten React Native tai Flutter, jotka hyödyntävät JavaScriptiä:
- Web-näkymät: Jos mobiilisovelluksesi käyttää web-näkymää web-sisällön näyttämiseen, samat CORS-säännöt pätevät kuin verkkoselaimessa. Määritä palvelimesi sallimaan pyynnöt web-sisällön originilta.
- React Native/Flutter: Nämä kehykset käyttävät JavaScriptiä API-pyyntöjen tekemiseen. Vaikka natiiviympäristö ei välttämättä pakota CORS:ia suoraan, pohjalla olevat HTTP-asiakkaat (esim.
fetch) voivat silti näyttää CORS-tyyppistä käyttäytymistä tietyissä tilanteissa. - Natiivit HTTP-asiakkaat: Kun teet API-pyyntöjä suoraan natiivikoodista (esim. käyttämällä OkHttp:tä Androidilla tai URLSession:ia iOS:lla), CORS ei yleensä ole tekijä. Sinun on kuitenkin silti harkittava turvallisuuden parhaita käytäntöjä, kuten asianmukaista todennusta ja valtuutusta.
Globaalit huomioonotettavat seikat CORS-konfiguraatiossa
Määritettäessä CORS globaalisti saatavilla olevalle sovellukselle, on ratkaisevan tärkeää harkita seuraavia tekijöitä:
- Tiedon suvereniteetti: Joissakin alueissa säännöt vaativat tietojen sijaitsemisen alueella. CORS voi olla mukana, kun käytetään resursseja rajojen yli, mikä voi olla vastoin tiedon asuinpaikan lakeja.
- Alueelliset turvallisuuskäytännöt: Eri mailla voi olla erilaisia kyberturvallisuusmääräyksiä ja -ohjeita, jotka vaikuttavat siihen, miten CORS tulisi toteuttaa ja suojata.
- Sisällönjakeluverkot (CDN:t): Varmista, että CDN:si on oikein määritetty välittämään tarvittavat CORS-otsikot. Virheellisesti määritetyt CDN:t voivat poistaa CORS-otsikoita, mikä johtaa odottamattomiin virheisiin.
- Kuormantasaajat ja proxyt: Tarkista, että kaikki infrastruktuurissasi olevat kuormantasaajat tai käänteiset proxyt käsittelevät esitarkistuspyyntöjä ja välittävät CORS-otsikoita oikein.
- Monikielinen tuki: Harkitse, miten CORS on vuorovaikutuksessa sovelluksesi kansainvälistymis- (i18n) ja lokalisointistrategioiden (l10n) kanssa. Varmista, että CORS-käytännöt ovat yhdenmukaisia sovelluksesi eri kieliversioissa.
CORS:n testaaminen ja virheenkorjaus
CORS:n tehokas testaaminen ja virheenkorjaus on elintärkeää. Tässä on joitain tekniikoita:
- Selaimen kehittäjätyökalut: Selaimen kehittäjän konsoli on ensimmäinen pysähdyspaikkasi. "Network"-välilehti näyttää esitarkistuspyynnöt ja vastaukset paljastaen, ovatko CORS-otsikot läsnä ja oikein määritettyjä.
- `curl`-komentorivityökalu: Käytä `curl -v -X OPTIONS
` lähettääksesi manuaalisesti esitarkistuspyyntöjä ja tarkastellaksesi palvelimen vastausotsikoita. - Verkossa olevat CORS-tarkistajat: Lukuisat verkkotyökalut voivat auttaa validoimaan CORS-konfiguraatiosi. Etsi vain "CORS checker".
- Yksikkö- ja integraatiotestit: Kirjoita automatisoituja testejä tarkistaaksesi, että CORS-konfiguraatiosi toimii odotetusti. Näiden testien tulisi kattaa sekä onnistuneet cross-origin-pyynnöt että skenaariot, joissa CORS:n tulisi estää pääsy.
- Kirjaaminen ja valvonta: Toteuta lokitus CORS-tapahtumien, kuten esitarkistuspyyntöjen ja estettyjen pyyntöjen, seuraamiseksi. Tarkkaile lokejasi epäilyttävän toiminnan tai konfigurointivirheiden varalta.
Lopuksi
Cross-Origin Resource Sharing (CORS) on elintärkeä turvallisuusmekanismi, joka mahdollistaa hallitun cross-origin-pääsyn web-resursseihin. CORS:n toiminnan ymmärtäminen, erityisesti esitarkistuspyynnöt, on ratkaisevan tärkeää turvallisten ja luotettavien web-sovellusten rakentamisessa. Noudattamalla tässä oppaassa esitettyjä parhaita käytäntöjä voit tehokkaasti käsitellä CORS-ongelmia ja suojata sovelluksesi mahdollisilta haavoittuvuuksilta. Muista asettaa turvallisuus aina etusijalle ja harkita huolellisesti CORS-konfiguraatiosi vaikutuksia.
Web-kehityksen kehittyessä CORS on jatkossakin kriittinen osa verkkoturvallisuutta. Pysyminen ajan tasalla uusimmista CORS-parhaista käytännöistä ja tekniikoista on välttämätöntä turvallisten ja globaalisti käytettävissä olevien web-sovellusten rakentamiseksi.