Atskleiskite CORS (skirtingų šaltinių išteklių bendrinimo) paslaptis ir sužinokite, kaip saugiai įgalinti tarpdomenines užklausas savo interneto programose. Šis išsamus vadovas apima viską nuo pagrindų iki pažangių konfigūracijų, užtikrinant sklandų ir saugų ryšį tarp skirtingų šaltinių.
CORS demistifikavimas: išsamus vadovas apie skirtingų šaltinių išteklių bendrinimą
Šiuolaikiniame tarpusavyje susijusiame internete programoms dažnai reikia pasiekti išteklius iš skirtingų šaltinių. Būtent čia į pagalbą ateina skirtingų šaltinių išteklių bendrinimas (CORS). CORS yra esminis saugumo mechanizmas, kuris reguliuoja, kaip interneto naršyklės tvarko užklausas iš vieno šaltinio (domeno, protokolo ir prievado) į kitą. Suprasti CORS yra būtina kiekvienam žiniatinklio kūrėjui, norinčiam kurti saugias ir funkcionalias interneto programas.
Kas yra tos pačios kilmės politika?
Prieš gilinantis į CORS, svarbu suprasti tos pačios kilmės politiką (SOP – Same-Origin Policy). SOP yra fundamentalus saugumo mechanizmas, įdiegtas interneto naršyklėse. Jo tikslas yra neleisti kenkėjiškiems scenarijams vienoje svetainėje pasiekti jautrių duomenų kitoje svetainėje. Šaltinis yra apibrėžiamas protokolo (pvz., HTTP arba HTTPS), domeno (pvz., example.com) ir prievado numerio (pvz., 80 arba 443) deriniu. Du URL laikomi turinčiais tą patį šaltinį, jei jų protokolas, domenas ir prievadas sutampa.
Pavyzdys:
http://example.com/app1
irhttp://example.com/app2
- Tas pats šaltinis (tas pats protokolas, domenas ir prievadas)https://example.com/app1
irhttp://example.com/app1
- Skirtingas šaltinis (skirtingas protokolas)http://example.com:8080/app1
irhttp://example.com/app1
- Skirtingas šaltinis (skirtingas prievadas)http://sub.example.com/app1
irhttp://example.com/app1
- Skirtingas šaltinis (skirtingas subdomenas – laikomas skirtingu domenu)
SOP riboja scenarijų galimybes pasiekti išteklius iš skirtingo šaltinio, nebent yra įdiegtos specialios priemonės, tokios kaip CORS, leidžiančios tai daryti.
Kodėl CORS yra būtinas?
Nors tos pačios kilmės politika yra gyvybiškai svarbi saugumui, ji taip pat gali būti ribojanti. Daugelis šiuolaikinių interneto programų remiasi duomenų gavimu iš skirtingų serverių, pavyzdžiui, API ar turinio pristatymo tinklų (CDN). CORS suteikia kontroliuojamą būdą sušvelninti SOP ir leisti teisėtas skirtingų šaltinių užklausas, išlaikant saugumą.
Apsvarstykite scenarijų, kai interneto programa, talpinama http://example.com
, turi gauti duomenis iš API serverio, talpinamo http://api.example.net
. Be CORS naršyklė blokuotų šią užklausą dėl SOP. CORS leidžia API serveriui aiškiai nurodyti, kuriems šaltiniams leidžiama pasiekti jo išteklius, taip įgalinant teisingą interneto programos veikimą.
Kaip veikia CORS: pagrindai
CORS veikia per HTTP antraščių mainus tarp kliento (naršyklės) ir serverio. Serveris naudoja šias antraštes informuoti naršyklę, ar jai leidžiama pasiekti prašomą išteklių. Pagrindinė susijusi HTTP antraštė yra Access-Control-Allow-Origin
.
1 scenarijus: paprasta užklausa
„Paprasta užklausa“ yra GET, HEAD arba POST užklausa, atitinkanti specifinius kriterijus (pvz., Content-Type
antraštė yra viena iš application/x-www-form-urlencoded
, multipart/form-data
arba text/plain
). Tokiu atveju naršyklė siunčia užklausą tiesiai į serverį, o serveris atsako su Access-Control-Allow-Origin
antrašte.
Kliento užklausa (iš http://example.com):
GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Serverio atsakymas (iš http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"data": "Kažkokie duomenys iš serverio"
}
Šiame pavyzdyje serveris atsako su Access-Control-Allow-Origin: http://example.com
, nurodydamas, kad užklausos iš http://example.com
yra leidžiamos. Jei užklausos šaltinis neatitinka Access-Control-Allow-Origin
antraštės vertės (arba jei antraštė neegzistuoja), naršyklė blokuos atsakymą ir neleis kliento pusės scenarijui pasiekti duomenų.
2 scenarijus: parengiamoji užklausa (sudėtingoms užklausoms)
Sudėtingesnėms užklausoms, tokioms kaip tos, kurios naudoja HTTP metodus PUT, DELETE, ar tos, kurios turi nestandartines antraštes, naršyklė atlieka „parengiamąją užklausą“ (angl. preflight request) naudodama HTTP OPTIONS metodą. Ši parengiamoji užklausa prašo serverio leidimo prieš siunčiant tikrąją užklausą. Serveris atsako su antraštėmis, kurios nurodo, kurie metodai, antraštės ir šaltiniai yra leidžiami.
Kliento parengiamoji užklausa (iš 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
Serverio atsakymas (iš 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
Antraščių paaiškinimas:
Access-Control-Allow-Origin: http://example.com
- Nurodo, kad užklausos išhttp://example.com
yra leidžiamos.Access-Control-Allow-Methods: GET, PUT, DELETE
- Nurodo HTTP metodus, leidžiamus skirtingų šaltinių užklausoms.Access-Control-Allow-Headers: X-Custom-Header, Content-Type
- Išvardija leidžiamas nestandartines antraštes tikrojoje užklausoje.Access-Control-Max-Age: 3600
- Nurodo trukmę (sekundėmis), kiek laiko parengiamasis atsakymas gali būti saugomas naršyklės talpykloje. Tai padeda sumažinti parengiamųjų užklausų skaičių.
Jei serverio parengiamasis atsakymas rodo, kad užklausa yra leidžiama, naršyklė tęsia siųsdama tikrąją užklausą. Priešingu atveju naršyklė blokuoja užklausą.
Kliento tikroji užklausa (iš 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": "Kažkokie duomenys, kuriuos reikia atnaujinti"
}
Serverio atsakymas (iš http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"status": "Duomenys sėkmingai atnaujinti"
}
Dažniausios CORS antraštės
Štai pagrindinių CORS antraščių, kurias turite suprasti, apžvalga:
Access-Control-Allow-Origin
: Tai pati svarbiausia antraštė. Ji nurodo šaltinį(-ius), kuriems leidžiama pasiekti išteklių. Galimos vertės:- Konkretus šaltinis (pvz.,
http://example.com
). *
(pakaitos simbolis): Leidžia užklausas iš bet kurio šaltinio. Naudokite atsargiai, nes tai gali pakenkti saugumui, jei perduodami jautrūs duomenys. Paprastai to reikėtų vengti produkcinėse aplinkose.
- Konkretus šaltinis (pvz.,
Access-Control-Allow-Methods
: Ši antraštė nurodo HTTP metodus (pvz., GET, POST, PUT, DELETE), kurie leidžiami skirtingų šaltinių užklausoms. Ji naudojama parengiamajame atsakyme.Access-Control-Allow-Headers
: Ši antraštė išvardija nestandartines antraštes, kurios leidžiamos skirtingų šaltinių užklausose. Ji taip pat naudojama parengiamajame atsakyme.Access-Control-Allow-Credentials
: Ši antraštė nurodo, ar serveris leidžia įtraukti kredencialus (pvz., slapukus, autorizacijos antraštes) į skirtingų šaltinių užklausas. Ji turėtų būti nustatyta įtrue
, jei reikia siųsti kredencialus. Kliento pusėje taip pat reikia nustatytiwithCredentials = true
XMLHttpRequest objekte.Access-Control-Expose-Headers
: Pagal numatytuosius nustatymus naršyklės kliento pusės scenarijams atskleidžia tik ribotą atsakymo antraščių rinkinį (pvz.,Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
). Jei norite atskleisti kitas antraštes, turite jas išvardytiAccess-Control-Expose-Headers
antraštėje.Access-Control-Max-Age
: Ši antraštė nurodo maksimalų laiką (sekundėmis), kiek naršyklė gali talpinti parengiamosios užklausos atsakymą. Ilgesnė vertė sumažina parengiamųjų užklausų skaičių ir pagerina našumą.
CORS skirtingose serverio pusės kalbose
CORS įgyvendinimas paprastai apima serverio pusės programos konfigūravimą, kad ji siųstų atitinkamas CORS antraštes. Štai pavyzdžiai, kaip tai padaryti įvairiose kalbose ir sistemose:
Node.js su Express
Galite naudoti cors
tarpinės programinės įrangos paketą:
const express = require('express');
const cors = require('cors');
const app = express();
// Įjungti CORS visiems šaltiniams (PRODUKCINĖJE APLINKOJE NAUDOTI ATSARGIAI)
app.use(cors());
// Arba konfigūruoti CORS konkretiems šaltiniams
// app.use(cors({
// origin: 'http://example.com'
// }));
app.get('/data', (req, res) => {
res.json({ message: 'Tai yra CORS įgalinta visiems šaltiniams!' });
});
app.listen(3000, () => {
console.log('Serveris veikia 3000 prievade');
});
Python su Flask
Galite naudoti Flask-CORS
plėtinį:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# Arba konfigūruoti CORS konkretiems šaltiniams
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})
@app.route("/data")
def hello():
return {"message": "Tai yra CORS įgalinta visiems šaltiniams!"}
if __name__ == '__main__':
app.run(debug=True)
Java su Spring Boot
Galite konfigūruoti CORS savo Spring Boot programoje naudodami anotacijas arba konfigūracijos klases:
Naudojant anotacijas:
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") // Leisti užklausas iš http://example.com
public class DataController {
@GetMapping("/data")
public String getData() {
return "Tai yra CORS įgalinta http://example.com!";
}
}
Naudojant konfigūraciją:
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") // Leisti užklausas iš http://example.com
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
}
PHP
"Tai yra CORS įgalinta http://example.com!");
echo json_encode($data);
?>
CORS ir saugumo aspektai
Nors CORS įgalina skirtingų šaltinių užklausas, labai svarbu jį įgyvendinti saugiai. Štai keletas svarbių aspektų:
- Venkite naudoti
*
Access-Control-Allow-Origin
antraštėje produkcinėje aplinkoje: Tai leidžia užklausas iš bet kurio šaltinio, o tai gali būti saugumo rizika. Vietoj to, aiškiai nurodykite šaltinius, kuriems leidžiama pasiekti jūsų išteklius. - Patikrinkite
Origin
antraštę serverio pusėje: Net jei naudojate sistemą, kuri tvarko CORS konfigūraciją, gera praktika yra patikrintiOrigin
antraštę serverio pusėje, kad įsitikintumėte, jog užklausa ateina iš laukiamo šaltinio. - Būkite atidūs su
Access-Control-Allow-Credentials
: Jei naudojate kredencialus (pvz., slapukus, autorizacijos antraštes), įsitikinkite, kad nustatėteAccess-Control-Allow-Credentials: true
serverio pusėje irwithCredentials = true
kliento pusėje. Tačiau atminkite, kad naudotiAccess-Control-Allow-Origin: *
neleidžiama, kaiAccess-Control-Allow-Credentials
yra nustatyta įtrue
. Turite aiškiai nurodyti leidžiamus šaltinius. - Tinkamai konfigūruokite
Access-Control-Allow-Methods
irAccess-Control-Allow-Headers
: Leiskite tik tuos HTTP metodus ir antraštes, kurie yra būtini jūsų programos teisingam veikimui. Tai padeda sumažinti atakos paviršių. - Naudokite HTTPS: Visada naudokite HTTPS savo interneto programoms ir API, kad apsaugotumėte duomenis perdavimo metu.
CORS problemų sprendimas
CORS problemų derinimas gali būti varginantis. Štai keletas dažniausių problemų ir kaip jas išspręsti:
- „No 'Access-Control-Allow-Origin' header is present on the requested resource“ (Prašomame ištekliuje nėra 'Access-Control-Allow-Origin' antraštės): Tai pati dažniausia CORS klaida. Ji reiškia, kad serveris nesiunčia
Access-Control-Allow-Origin
antraštės savo atsakyme. Dukart patikrinkite savo serverio pusės konfigūraciją, kad įsitikintumėte, jog antraštė siunčiama teisingai. - „Response to preflight request doesn't pass access control check: It does not have HTTP ok status“ (Atsakymas į parengiamąją užklausą nepraeina prieigos kontrolės patikrinimo: jis neturi HTTP ok būsenos): Ši klaida rodo, kad parengiamoji užklausa nepavyko. Taip gali nutikti, jei serveris nėra sukonfigūruotas tvarkyti OPTIONS užklausų arba jei
Access-Control-Allow-Methods
arAccess-Control-Allow-Headers
antraštės nėra sukonfigūruotos teisingai. - „The value of the 'Access-Control-Allow-Origin' header in the response is not equal to the origin in the request“ ('Access-Control-Allow-Origin' antraštės vertė atsakyme neatitinka užklausos šaltinio): Ši klaida reiškia, kad užklausos šaltinis neatitinka
Access-Control-Allow-Origin
antraštės vertės. Įsitikinkite, kad serveris siunčia teisingą šaltinį atsakyme. - Naršyklės podėliavimas (caching): Kartais naršyklės gali talpinti CORS atsakymus, o tai gali sukelti netikėtą elgseną. Pabandykite išvalyti naršyklės talpyklą arba naudoti kitą naršyklę, kad pamatytumėte, ar tai išsprendžia problemą. Taip pat galite naudoti
Access-Control-Max-Age
antraštę, kad kontroliuotumėte, kiek laiko naršyklė talpina parengiamojo atsakymo duomenis.
Derinimo įrankiai:
- Naršyklės kūrėjo įrankiai: Naudokite naršyklės kūrėjo įrankius (dažniausiai pasiekiami paspaudus F12), kad patikrintumėte tinklo užklausas ir atsakymus. Ieškokite su CORS susijusių antraščių ir klaidų pranešimų.
- Internetiniai CORS tikrintuvai: Yra internetinių įrankių, kurie gali padėti išbandyti jūsų CORS konfigūraciją. Šie įrankiai siunčia užklausą į jūsų serverį ir analizuoja atsakymo antraštes, kad nustatytų galimas problemas.
Pažangesni CORS scenarijai
Nors pagrindinės CORS sąvokos yra gana paprastos, yra keletas pažangesnių scenarijų, kuriuos verta apsvarstyti:
- CORS su subdomenais: Jei reikia leisti užklausas iš kelių subdomenų (pvz.,
app1.example.com
,app2.example.com
), negalite tiesiog naudoti pakaitos simbolio, pavyzdžiui,*.example.com
,Access-Control-Allow-Origin
antraštėje. Vietoj to, turėsite dinamiškai generuotiAccess-Control-Allow-Origin
antraštę, remdamiesi užklausosOrigin
antrašte. Nepamirškite patikrinti šaltinio pagal leistinų subdomenų baltąjį sąrašą, kad išvengtumėte saugumo pažeidžiamumų. - CORS su keliais šaltiniais: Jei reikia leisti užklausas iš kelių konkrečių šaltinių, negalite nurodyti kelių šaltinių
Access-Control-Allow-Origin
antraštėje (pvz.,Access-Control-Allow-Origin: http://example.com, http://another.com
yra negaliojanti). Vietoj to, turėsite dinamiškai generuotiAccess-Control-Allow-Origin
antraštę, remdamiesi užklausosOrigin
antrašte. - CORS ir CDN: Naudodami CDN savo API aptarnavimui, turite sukonfigūruoti CDN, kad jis persiųstų
Origin
antraštę į jūsų pagrindinį serverį ir teisingai talpintųAccess-Control-Allow-Origin
antraštę. Konkrečių instrukcijų ieškokite savo CDN teikėjo dokumentacijoje.
Geriausios CORS praktikos
Norėdami užtikrinti saugų ir efektyvų CORS įgyvendinimą, laikykitės šių geriausių praktikų:
- Mažiausių privilegijų principas: Leiskite tik minimalų šaltinių, metodų ir antraščių rinkinį, kuris yra būtinas jūsų programos teisingam veikimui.
- Reguliariai peržiūrėkite CORS konfigūraciją: Vystantis jūsų programai, reguliariai peržiūrėkite savo CORS konfigūraciją, kad įsitikintumėte, jog ji vis dar tinkama ir saugi.
- Naudokite sistemą ar biblioteką: Pasinaudokite esamomis sistemomis ar bibliotekomis, kurios teikia integruotą CORS palaikymą. Tai gali supaprastinti įgyvendinimą ir sumažinti klaidų riziką.
- Stebėkite CORS pažeidimus: Įdiekite stebėseną, kad aptiktumėte galimus CORS pažeidimus ir į juos reaguotumėte.
- Būkite atnaujinę: Sekite naujausias CORS specifikacijas ir saugumo rekomendacijas.
Išvada
CORS yra kritiškai svarbus saugumo mechanizmas, leidžiantis kontroliuojamas skirtingų šaltinių užklausas interneto programose. Suprasti, kaip veikia CORS ir kaip jį tinkamai sukonfigūruoti, yra būtina kiekvienam žiniatinklio kūrėjui. Vadovaudamiesi šiame išsamiame vadove pateiktomis gairėmis ir geriausiomis praktikomis, galite kurti saugias ir funkcionalias interneto programas, kurios sklandžiai sąveikauja su ištekliais iš skirtingų šaltinių.
Nepamirškite visada teikti pirmenybę saugumui ir vengti pernelyg liberalių CORS konfigūracijų. Atidžiai apsvarstydami savo CORS nustatymų saugumo pasekmes, galite apsaugoti savo programas ir duomenis nuo neteisėtos prieigos.
Tikimės, kad šis vadovas padėjo jums demistifikuoti CORS. Sėkmingo programavimo!