Für einen erfahrenen Entwickler mag dieser Text nicht überraschend sein, aber ich denke, dass viele Artikel, die ich über das CORS-Setup in Rails gelesen habe, so etwas sagen wie: Verwenden Sie rack-cors, erlauben Sie jedem Host den Zugriff auf die API, und (optional): Sie sollten etwas anderes (als das Zulassen jedes Hosts) in der Produktion in Betracht ziehen.
Die vorgeschlagene Code war immer in der Nähe des darunter liegenden:
config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins ''
resource '', Kopfzeilen: :any, Methoden: :any
end
end
und leider haben uns diese Texte kaum erklärt, was wir in der Produktion tatsächlich tun sollen.
Ich komme mit dem Kopieren und Einfügen gut zurecht (Ich scherze manchmal, dass Unternehmen einen Stack Overflow Copy-Paster einstellen könnten.), da zwischen "Kopieren" und "Einfügen" ein Moment des "Nachdenkens und Anpassen" liegt. Ich möchte also ein wenig näher erläutern, was wir hier tun und wie es im wirklichen Leben funktioniert.
Ich hoffe, es macht Ihnen nichts aus, wenn ich mit einer kurzen Einführung in die Ehrentheorie beginne und dann zu den Rails-Beispielen übergehe.
Einführung
Fangen wir von vorne an. Um die Dinge besser zu erklären, habe ich die Einführung in drei Teile aufgeteilt. Im ersten Teil wird erläutert, was ein Ursprung ist - der Schlüsselbegriff für das, worüber wir hier sprechen. Im zweiten Teil geht es um die SOP, nur eine kurze Beschreibung. Und im letzten Teil geht es um die CORS
selbst.
Was ist ein Ursprung?
Laut den MDN Web Docs:
- Der Ursprung von Webinhalten wird durch das Schema (Protokoll), den Host (Domäne) und den Port der URL definiert, die für den Zugriff auf den Inhalt verwendet wird. Zwei Objekte haben nur dann denselben Ursprung, wenn das Schema, der Host und der Port übereinstimmen (Quelle)
Das scheint ziemlich klar zu sein, nicht wahr? Analysieren wir zwei Beispiele aus MDN, nur für den Fall.
http://example.com/app1/index.html
, http://example.com/app2/index.html
Die 2 oben genannten haben nämlich denselben Ursprung:
- ihre Systeme (http) sind die gleichen,
- ihre Domänen (example.com) sind identisch,
- ihre (impliziten) Ports sind die gleichen.
http://www.example.com
, http://myapp.example.com
Diese 2 haben einen unterschiedlichen Ursprung, da die Bereiche (www.example.com
, myapp.beispiel.de
) sind unterschiedlich.
Ich hoffe, das ist klar genug. Falls nicht, finden Sie weitere Beispiele in den MDN Web Docs.
Was ist SOP?
MDN Web Docs sagt (Quelle):
- Die Richtlinie gleichen Ursprungs ist ein wichtiger Sicherheitsmechanismus, der einschränkt, wie ein von einem Ursprung geladenes Dokument oder Skript mit einer Ressource eines anderen Ursprungs interagieren kann. Sie hilft, potenziell bösartige Dokumente zu isolieren und mögliche Angriffsvektoren zu reduzieren.
- Herkunftsübergreifende Schreibvorgänge sind in der Regel erlaubt. Beispiele sind Links, Weiterleitungen und Formularübermittlungen.
- Die herkunftsübergreifende Einbettung ist in der Regel zulässig.
- Herkunftsübergreifende Lesevorgänge sind in der Regel nicht erlaubt, aber der Lesezugriff wird oft durch Einbettung erschlichen.
Verwenden Sie CORS
um einen herkunftsübergreifenden Zugang zu ermöglichen
Wie Sie sehen, gibt es in den Definitionen von SOP viel über herkunftsübergreifendes Verhalten. Das ist in Ordnung. Alles, was wir jetzt wissen sollten, ist, dass derselbe Ursprung mehr Privilegien hat und wir die Regeln für Cross-Origin durch die Verwendung von CORS lockern können. Und hier kommt der nächste Abschnitt ins Spiel.
Was ist CORS?
In Anlehnung an MDNs Worte:
- Cross-Origin Resource Sharing (CORS) ist ein auf HTTP-Header basierender Mechanismus, der es einem Server ermöglicht, andere Ursprünge (Domäne, Schema oder Port) als seinen eigenen anzugeben, von denen ein Browser das Laden von Ressourcen erlauben soll. CORS stützt sich auch auf einen Mechanismus, mit dem die Browser eine "Preflight"-Anfrage an den Server stellen, der die herkunftsübergreifende Ressource hostet, um zu prüfen, ob der Server die eigentliche Anfrage zulässt. In diesem Preflight sendet der Browser Kopfzeilen, die die HTTP-Methode und die Kopfzeilen angeben, die in der eigentlichen Anfrage verwendet werden sollen (Quelle).
Das ist immer noch nicht genug. Was dort nicht ausdrücklich gesagt wurde, ist, dass die wichtigste Kopfzeile bei der Verwendung von CORS
ist Zugriffskontrolle-Ursprung zulassen
:
- Die
Zugriffskontrolle-Ursprung zulassen
Response-Header gibt an, ob die Antwort mit dem anfragenden Code des angegebenen Ursprungs gemeinsam genutzt werden kann (Quelle).
Nun, das sollte es sein. Im wirklichen Leben, beim Konfigurieren von CORS
konfigurieren wir normalerweise die ACAO
Kopfzeile zuerst.
Das wahre Leben
Das war's mit den Definitionen. Kehren wir zurück zu Rails und den Beispielen aus der Praxis.
Wie konfiguriert man CORS in Rails?
Wir werden auf jeden Fall Rack-Cors verwenden (wie uns gesagt wurde). Erinnern wir uns an den ersten Ausschnitt, der in anderen Artikeln am häufigsten vorkommt:
config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins ''
resource '', Kopfzeilen: :any, Methoden: :any
end
end
Die Zahl der Möglichkeiten ist riesig oder sogar unendlich, aber lassen Sie uns diese beiden betrachten:
- wir bauen die API auf, die von Browser-Clients von Drittanbietern verwendet werden darf,
- wir haben eine typische Frontend/Backend-Trennung und wollen unseren vertrauenswürdigen Kunden den Zugriff auf die API ermöglichen.
Gebäude-API für den Zugriff durch Drittanbieter-Clients
Wenn Sie sich mit der ersten Option konfrontiert sehen, können Sie sich wahrscheinlich für Ursprünge
*' - Sie wollen, dass andere einen Client auf der Grundlage Ihrer API erstellen, und wissen nicht, wer sie sind, richtig?
Typische Frontend/Backend-Trennung
Wenn Sie letzteres entwickeln, wollen Sie wahrscheinlich nicht, dass jeder Anfragen an Ihre API stellt, die sich über mehrere Herkunftsländer erstrecken. Sie wollen es vielmehr:
- Produktions-Clients den Zugriff auf die Produktions-API ermöglichen,
- dasselbe für die Inszenierung,
- dasselbe für localhost,
- können Sie FE-Review-Anwendungen den Zugriff auf Staging erlauben.
Wir werden weiterhin Rack-Cors verwenden (wie es uns gesagt wurde) - aber auf unsere Art.
Verwenden wir 2 ENV-Variablen: ERLAUBTE_URSPRÜNGE
für wörtliche Ursprungsdefinitionen (ein Sternchen oder eine tatsächliche URL) und ALLOWED_ORIGIN_REGEXPS
für die Muster.
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)
Ressource '*',
methods: %i[get post put patch delete options head],
Kopfzeilen: :any
end
end
Was ist denn hier los?
- Wie Sie sehen, trennen wir die in den ENV-Variablen definierten Werte mit verschiedenen Trennzeichen. Das liegt daran, dass ein Semikolon im URL-Definitionsmuster seltener vorkommt.
- Literale Werte sind einsatzbereit, aber wir müssen die Muster auf tatsächliche Regexp-Instanzen abbilden.
- Dann fügen wir alles zusammen und erlauben diesen Hosts den Zugriff auf jede Ressource mit den von unserer API verwendeten Whitelist-Methoden.
Dies sollte Ihnen genügend Flexibilität geben, um in Ihren Entwicklungs-, Staging- und Produktionsumgebungen die richtigen Werte zu definieren.
Schlussfolgerungen
Fassen wir die oben genannten Punkte in Stichpunkten zusammen:
- ENV-Variablen zur Konfiguration verwenden
CORS
,
- Verwendung regulärer Ausdrücke, um den Zugriff auf die Staging-API für verschiedene Herkunftsländer zu ermöglichen (z. B. für Prüfanwendungen),
- Zwischen "Kopieren" und "Einfügen" sollte immer "Überlegen und anpassen" stehen.
Das war's schon. Einen schönen Tag noch! 🙂
Lesen Sie mehr:
Warum sollten Sie (wahrscheinlich) Typescript verwenden?
10 erwähnenswerte NYC-Startups im Jahr 2021