Patyrusiam kūrėjui šis tekstas gali būti visai netikėtas, tačiau manau, kad daugelyje straipsnių, kuriuos skaičiau apie CORS sąranką "Rails", buvo rašoma maždaug taip: naudokite "rack-cors", leiskite bet kuriam prieglobos kompiuteriui pasiekti API ir (pasirinktinai): gamyboje turėtumėte apsvarstyti ką nors kita (nei leisti bet kuriam prieglobos kompiuteriui).
Siūloma kodas visada buvo arti žemiau esančio:
config/initializers/cors.rb
Bėgiai.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins ''
resource '', headers: :any, methods: :any
end
end
ir, deja, šie tekstai buvo vargu ar paaiškinti mus ką iš tikrųjų reikia daryti gamyboje.
Man visai neblogai sekasi kopijuoti ir dėti (Kartais juokauju, kad įmonės galėtų pasamdyti "Stack Overflow" kopijavimo meistrą), nes tarp “kopijuoti” ir “įklijuoti” yra momentas “pagalvok ir prisitaikyk”. Taigi norėčiau šiek tiek paaiškinti, ką mes čia darome ir kaip tai veikia realiame gyvenime.
Tikiuosi, neprieštaraujate, kad pradėsiu nuo trumpo įvado į garbės teoriją ir pereisiu prie "Rails" pavyzdžių.
Įvadas
Pradėkime nuo pradžių. Kad viską geriau paaiškinčiau, įžangą suskirsčiau į tris dalis. Pirmoje dalyje bus išdėstyta, kas yra kilmė - pagrindinė sąvoka tam, ką čia aptariame. Antrojoje - apie SOP, tik trumpas apibūdinimas. O paskutinėje dalyje kalbama apie CORS pati.
Kas yra kilmė?
Pasak MDN Tinklalapis Dokumentai:
- Žiniatinklio turinio kilmė nustatoma pagal URL adreso, kuriuo jis pasiekiamas, schemą (protokolą), prieglobstį (domeną) ir prievadą. Du objektai yra tos pačios kilmės tik tada, kai sutampa schema, prieglobstis ir prievadas (šaltinis)
Tai atrodo gana aišku, ar ne? Paanalizuokime du pavyzdžius iš MDN.
http://example.com/app1/index.html, http://example.com/app2/index.html
2 aukščiau išvardyti žodžiai yra tos pačios kilmės, nes:
- jų schemos (http) yra vienodos,
- jų domenai (example.com) yra vienodi,
- jų prievadai (numanomi) yra vienodi.
http://www.example.com, http://myapp.example.com
Šių 2 sričių kilmė yra skirtinga, nes domenai (www.example.com, myapp.example.com) skiriasi.
Tikiuosi, kad viskas pakankamai aišku. Jei ne, daugiau pavyzdžių rasite MDN interneto dokumentuose.
Kas yra SOP?
MDN žiniatinklio dokumentuose sakoma (šaltinis):
- Tos pačios kilmės politika - tai svarbus saugumo mechanizmas, kuriuo ribojama, kaip iš vienos kilmės šaltinio įkeltas dokumentas ar scenarijus gali sąveikauti su kitos kilmės šaltiniu. Ji padeda atskirti galimai kenkėjiškus dokumentus ir sumažinti galimus atakos vektorius.
- Įprastai leidžiami kryžminės kilmės įrašai. Pavyzdžiai - nuorodos, nukreipimai ir formų pateikimas.
- Įprastai leidžiama įterpti skirtingų kilmės šalių duomenis.
- Paprastai kryžminis skaitymas paprastai neleidžiamas, tačiau skaitymo prieiga dažnai nutekinama įterpiant.
Naudokite CORS kad būtų galima pasiekti įvairios kilmės šaltinius.
Kaip matote, SOP apibrėžtyse daug kalbama apie tarpvalstybinę elgseną. Tai yra gerai. Dabar turėtume žinoti tik tiek, kad ta pati kilmė turi daugiau privilegijų, o naudojant CORS galime sušvelninti taisykles, taikomas kryžminėms kilmėms. Ir štai čia atsiranda kitas skyrius.
Kas yra CORS?
Remiantis MDN žodžiais:
- Kryžminės kilmės išteklių dalijimasis (CORS) - tai HTTP antraštėmis pagrįstas mechanizmas, leidžiantis serveriui nurodyti bet kokias kitas kilmės šalis (domenas, schema arba prievadas), iš kurių naršyklė turėtų leisti įkelti išteklius. CORS taip pat remiasi mechanizmu, pagal kurį naršyklės pateikia išankstinę užklausą serveriui, kuriame saugomi skirtingų kilmių ištekliai, kad patikrintų, ar serveris leis pateikti faktinę užklausą. Atlikdama šį išankstinį patikrinimą naršyklė siunčia antraštes, kuriose nurodomas HTTP metodas ir antraštės, kurios bus naudojamos faktinėje užklausoje (šaltinis).
To vis dar nepakanka. Nebuvo aiškiai pasakyta, kad svarbiausia antraštė naudojant CORS yra . Access-Control-Allow-Origin:
- Svetainė
Access-Control-Allow-Origin atsakymo antraštė nurodo, ar atsakymą galima bendrinti su kodu, prašančiu iš tam tikros kilmės (šaltinis).
Tai turėtų būti viskas. Realiame gyvenime, konfigūruojant CORS, paprastai konfigūruojame ACAO pirmiausia antraštė.
Realus gyvenimas
Tai viskas, kai kalbama apie apibrėžimus. Grįžkime prie Rails ir realių pavyzdžių.
Kaip sukonfigūruoti CORS "Rails" sistemoje?
Mes būtinai naudosime stovo kortežus (kaip mums buvo pasakyta). Prisiminkime pirmąją ištrauką, kuri dažniausiai pateikiama kituose straipsniuose:
config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins ''
resource '', headers: :any, methods: :any
end
end
Galimybių yra labai daug ar net begalė, bet apsvarstykime šias dvi:
- kuriame API kurią leidžiama naudoti trečiųjų šalių naršyklių klientams,
- mes tipiškai atskyrėme frontendą ir backendą ir norime, kad mūsų patikimi klientai galėtų pasiekti API.
API kūrimas, kuriuo naudojasi trečiųjų šalių klientai
Jei pasirenkate pirmąjį variantą, tikriausiai galite rinktis kilmė ‘*’ - norite, kad kiti sukurtų klientą ant jūsų API, bet nežinote, kas jie yra, tiesa?
Tipiškas frontend ir backend atskyrimas
Jei kuriate pastarąją, tikriausiai nenorite, kad visi vykdytų skirtingų kilmės šalių užklausas į jūsų API. Jūs veikiau norite:
- leisti gamybiniams klientams naudotis gamybine API,
- tas pats pasakytina ir apie inscenizaciją,
- tas pats ir "localhost" atveju,
- galbūt norėsite leisti, kad FE peržiūros programos galėtų pasiekti stadiją.
Mes vis dar naudosime korsetus (kaip mums buvo liepta), bet mūsų būdu.
Naudokime 2 ENV kintamuosius: LEISTINOS_PRADŽIOS pažodinėms kilmės apibrėžtims (žvaigždutė arba tikrasis URL) ir LEISTINOS_PRADŽIOS_REGEKSPS modeliams.
config/initializers/cors.rb
frozenstringliteral: true
toregexp = ->(string) { Regexp.new(string) }
hosts = [
*ENV.fetch('ALLOWEDORIGINS').split(','),
*ENV.fetch('ALLOWEDORIGINREGEXPS').split(';').map(&to_regexp)
]
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins(*hosts)
resource '*',
methods: %i[get post put patch delete options head],
headers: :any
pabaiga
end
Kas čia vyksta?
- Kaip matote, ENV kintamuosiuose apibrėžtas reikšmes skirstome skirtingais skyrikliais. Taip yra todėl, kad URL apibrėžimo šablone yra mažesnė tikimybė, kad atsiras kabliataškis.
- Pažodinės reikšmės yra paruoštos naudoti, tačiau turime atvaizduoti šablonus kaip tikrus "Regexp" egzempliorius.
- Tada viską sujungiame ir leidžiame šiems prieglobsčio serveriams pasiekti bet kurį išteklių, kurio metodai įtraukti į baltąjį sąrašą, kurį naudoja mūsų API.
Tai turėtų suteikti pakankamai lankstumo, kad galėtumėte nustatyti tinkamas vertes kūrimo, stadijos ir gamybos aplinkose.
Išvados
Apibendrinkime visus pirmiau minėtus dalykus pagrindiniais punktais:
- naudoti ENV kintamuosius konfigūruojant
CORS,
- naudoti reguliarias išraiškas, kad skirtingos kilmės programoms būtų leidžiama pasiekti stabdymo API (pvz., peržiūros programoms),
- tarp “kopijuoti” ir “įklijuoti” visada įterpkite “pagalvoti ir pritaikyti”.
Štai ir viskas. Geros dienos! 🙂
Skaityti daugiau:
Kodėl turėtumėte (tikriausiai) naudoti Typescript?
10 Niujorko startuolių, kuriuos verta paminėti 2021 m.