Advertisement
  1. Code
  2. Ruby

Mit Sinatra singen - The Encore

Scroll to top
Read Time: 10 min
This post is part of a series called Singing with Sinatra.
Singing With Sinatra: The Recall App

German (Deutsch) translation by Valentina (you can also view the original English article)

Willkommen zurück beim Singen mit Sinatra! In diesem dritten und letzten Teil werden wir die "Recall"-App erweitern, die wir in der vorherigen Lektion erstellt haben. Wir werden der App einen RSS-Feed mit dem unglaublich nützlichen Builder-gem hinzufügen, mit dem das Erstellen von XML-Dateien in Ruby zum Kinderspiel wird. Wir werden lernen, wie einfach Sinatra es macht, HTML aus Benutzereingaben zu entfernen, um XSS-Angriffe zu verhindern, und wir werden einige der Fehlerbehandlungscodes verbessern.


Benutzer sind schlecht, m'kay

Die allgemeine Regel beim Erstellen von Web-Apps lautet, paranoid zu sein. Paranoid, dass jeder Ihrer Benutzer darauf aus ist, Sie zu erreichen, indem er Ihre Website zerstört oder andere Benutzer dadurch angreift. Versuchen Sie in Ihrer App, eine neue Notiz mit folgendem Inhalt hinzuzufügen:

Derzeit können unsere Benutzer beliebiges HTML eingeben. Dadurch bleibt die App für XSS-Angriffe offen, bei denen ein Benutzer möglicherweise bösartiges JavaScript eingibt, um andere Benutzer der Website anzugreifen oder fehlzuleiten. Das erste, was wir tun müssen, ist, alle vom Benutzer eingereichten Inhalte zu maskieren, damit der obige Code wie folgt in HTML-Entitäten konvertiert wird:

Fügen Sie dazu der recall.rb den folgenden Codeblock hinzu, z. B. unter DataMapper.auto_upgrade! Linie:

Dies umfasst eine Reihe von Methoden, die von Rack bereitgestellt werden. Wir haben jetzt Zugriff auf eine h()-Methode, um HTML zu umgehen.

Um HTML auf der Startseite zu umgehen, öffnen Sie die Ansichtsdatei views/home.erb und ändern Sie die Zeile <%=note.content%> (um Zeile 11) in:

Alternativ hätten wir dies als <%=h(note.content) %> schreiben können, aber der obige Stil ist in der Ruby-Community viel häufiger. Aktualisieren Sie die Seite und der übermittelte HTML-Code sollte jetzt maskiert und nicht vom Browser ausgeführt werden:

XSS auf den anderen Seiten

Klicken Sie auf den Link "Bearbeiten" für die Notiz mit dem XSS-Code, und Sie denken möglicherweise, dass sie sicher ist - alles befindet sich in einem Textbereich und wird daher nicht ausgeführt. Was aber, wenn wir eine neue Notiz mit folgendem Inhalt hinzufügen:

Werfen Sie einen Blick auf die Bearbeitungsseite, und Sie können sehen, dass wir den Textbereich geschlossen haben und die JavaScript-Warnung ausgeführt wird. Es ist also klar, dass wir den Inhalt der Notiz auf jeder Seite, auf der sie angezeigt wird, umgehen müssen.

Entfliehen Sie in Ihrer Ansichtsdatei views/edit.erb dem Inhalt im textarea, indem Sie ihn mit der Methode h ausführen (Zeile 4):

Und machen Sie dasselbe in Ihrer Datei views/delete.erb in Zeile 2:

Da haben Sie es - wir sind jetzt vor XSS sicher. Denken Sie daran, beim Erstellen anderer Webanwendungen in Zukunft alle vom Benutzer übermittelten Daten zu umgehen!

Sie fragen sich vielleicht: "Was ist mit SQL-Injektionen?" Nun, DataMapper erledigt das für uns genauso lange, wie wir DataMappers Methoden zum Abrufen von Daten aus der Datenbank verwenden (dh kein Raw-SQL ausführen).


RSS Füttern die Massen

Ein wichtiger Bestandteil jeder dynamischen Website ist eine Art RSS-Feed, und unsere Recall-App wird keine Ausnahme sein! Zum Glück ist es dank des Builder-gem unglaublich einfach, Feeds zu erstellen. Installieren Sie es mit:

Abhängig davon, wie Sie RubyGems auf Ihrem System eingerichtet haben, müssen Sie der gem install möglicherweise sudo voranstellen.

Fügen Sie nun Ihrer recall.rb-Anwendungsdatei eine neue Route für eine GET-Anforderung an /rss.xml hinzu:

Stellen Sie sicher, dass Sie diese Route irgendwo über der Route get'/:id' hinzufügen, da sonst eine Anfrage nach rss.xml mit einer Post-ID verwechselt wird!

In der Route fordern wir einfach alle Notizen aus der Datenbank an und laden eine rss.builder-Ansichtsdatei. Beachten Sie, wie wir früher die ERB-Engine zum Anzeigen einer .erb-Datei verwendet haben. Jetzt verwenden wir Builder zum Verarbeiten einer Datei. Eine Builder-Datei ist meist eine normale Ruby-Datei mit einem speziellen XML-Objekt zum Erstellen von xml-Tags.

Starten Sie Ihre Ansichtsdatei views/rss.builder wie folgt:

Sehr wichtiger Hinweis: Entfernen Sie in der ersten Sekunde des obigen Codeblocks den Punkt (.) Im Text :.xml. WordPress stört Code-Schnipsel.

Der Builder analysiert dies wie folgt:

Wir haben also zunächst die Struktur für eine gültige XML-Datei erstellt. Fügen wir nun Tags für den Feed-Titel, die Beschreibung und einen Link zurück zur Hauptseite hinzu. Fügen Sie im Block xml.channel do Folgendes hinzu:

Beachten Sie, wie wir die aktuelle URL vom request-Objekt erhalten. Wir könnten dies manuell codieren, aber die Idee ist, dass Sie die App überall hochladen können, ohne obskure Codeteile ändern zu müssen.

Es gibt jedoch ein Problem: Der Link ist jetzt (zum Beispiel) auf http://localhost:9393/rss.xml eingestellt. Idealerweise möchten wir, dass der Link zur Startseite und nicht zurück zum Feed führt. Das request-Objekt verfügt auch über eine path_info-Methode, die auf die aktuelle Routenzeichenfolge festgelegt ist. also in unserem Fall /rss.xml.

In diesem Wissen können wir jetzt Rubys chomp-Methode verwenden, um den Pfad vom Ende der URL zu entfernen. Ändern Sie die Zeile xml.link request.url in:

Der Link in unserer XML-Datei ist jetzt auf http://localhost:9393 festgelegt. Wir können jetzt jede Notiz durchlaufen und ein neues XML-Element dafür erstellen:

Beachten Sie, dass wir in den Zeilen 3 und 7 den Inhalt der Notiz mit h umgehen, genau wie in den Hauptansichten. Es ist etwas seltsam, sowohl für den title als auch für die description-Tags denselben Inhalt anzuzeigen, aber wir folgen hier dem Beispiel von Twitter, und es gibt keine anderen Daten, die wir dort ablegen können.

In Zeile 6 konvertieren wir die create_at-Zeit der Notiz in RFC822, das erforderliche Format für Zeiten in RSS-Feeds.

Probieren Sie es jetzt in einem Browser aus! Gehen Sie zu /rss.xml und Ihre Notizen sollten korrekt angezeigt werden.


TROCKEN Wiederholen Sie sich nicht

Bei unserer Implementierung gibt es ein kleines Problem. In unserer RSS-Ansicht haben wir den Site-Titel und die Beschreibung. Wir haben sie auch in der Datei views/layout.erb für den Hauptteil der Site. Wenn wir nun den Namen oder die Beschreibung der Site ändern möchten, müssen wir zwei verschiedene Stellen aktualisieren. Eine bessere Lösung wäre, den Titel und die Beschreibung an einer Stelle festzulegen und von dort aus auf sie zu verweisen.

Fügen Sie in der Anwendungsdatei recall.rb direkt nach den require-Anweisungen die folgenden zwei Zeilen am Anfang der Datei hinzu, um zwei Konstanten zu definieren:

Zurück in den views/rss.builder ändern Sie die Zeilen 4 und 5 in:

Und in den views/layout.erb ändern Sie das <title>-Tag in Zeile 5 in:

Ändern Sie die Titel-Tags h1 und h2 in den Zeilen 12 und 13 in:

Wir sollten auch einen Link zum RSS-Feed in den head der Seite einfügen, damit Browser eine RSS-Schaltfläche in der Adressleiste anzeigen können. Fügen Sie Folgendes direkt vor dem </head>-Tag hinzu:


Flash-Meldungen Fehler und Erfolge

Wir brauchen eine Möglichkeit, den Benutzer zu informieren, wenn etwas schief gelaufen ist - oder richtig, z. B. eine Bestätigungsnachricht, wenn eine neue Notiz hinzugefügt, eine Notiz entfernt usw. wird.

Der häufigste und logischste Weg, dies zu erreichen, sind "Flash-Nachrichten" - eine kurze Nachricht, die der Browsersitzung des Benutzers hinzugefügt wird und auf der nächsten Seite angezeigt und gelöscht wird. Und es gibt zufällig ein paar RubyGems, um dies zu erreichen! Geben Sie Folgendes in das Terminal ein, um Rack Flash und Sinatra Redirect mit Flash Gems zu installieren:

Abhängig davon, wie Sie RubyGems auf Ihrem System eingerichtet haben, müssen Sie der gem install möglicherweise sudo voranstellen.

Fordern Sie die Edelsteine an und aktivieren Sie ihre Funktionalität, indem Sie oben in Ihrer recall.rb-Anwendungsdatei Folgendes hinzufügen:

Das Hinzufügen einer neuen Flash-Nachricht ist so einfach wie flash[:error] = "Something went wrong!". Lassen Sie uns einen Fehler auf der Homepage anzeigen, wenn keine Notizen in der Datenbank vorhanden sind.

Ändern Sie Ihre get '/' Route in:

Sehr einfach. Wenn die Instanzvariable @notes leer ist, erstellen Sie einen neuen Flash-Fehler. Um diese Flash-Meldungen auf der Seite anzuzeigen, fügen Sie Ihrer Datei views/layout.erb vor <%= yield %> Folgendes hinzu:

Fügen Sie Ihrer Datei public/style.css die folgenden Stile hinzu, um Hinweise in Grün und Fehler in Rot anzuzeigen:

Jetzt sollte auf Ihrer Homepage die Meldung "Keine Notizen gefunden" angezeigt werden, wenn die Datenbank leer ist:

Lassen Sie uns nun entweder eine Fehler- oder eine Erfolgsmeldung anzeigen, je nachdem, ob der Datenbank eine neue Notiz hinzugefügt werden könnte. Ändern Sie Ihre post '/'-Route in:

Der Code ist ziemlich logisch. Wenn die Notiz gespeichert werden konnte, leiten Sie sie mit einer Flash-Meldung "Hinweis" auf die Startseite weiter. Andernfalls leiten Sie sie mit einer Flash-Fehlermeldung nach Hause weiter. Hier sehen Sie die alternative Syntax zum Festlegen einer Flash-Nachricht und zum Umleiten der Seite, die vom Juwel Sinatra-Redirect-With-Flash angeboten wird.

Ideal wäre es auch, einen Fehler auf der Seite "Notiz bearbeiten" anzuzeigen, wenn die angeforderte Notiz nicht vorhanden ist. Ändern Sie die Route get'/:id' in:

Und auch auf der PUT-Anforderungsseite zum Aktualisieren einer Notiz. Ändern Sie put '/:id' in:

Ändern Sie die Route get '/:id/delete' in:

Und die entsprechende DELETE-Anforderung delete '/:id' an:

Ändern Sie abschließend die Route get '/:id/complete' wie folgt:


Und da haben Sie es!

Eine funktionierende, sichere und auf Fehler reagierende Web-App, die in überraschend wenig Code geschrieben wurde! In dieser kurzen Miniserie haben wir gelernt, wie man verschiedene HTTP-Anforderungen mit einer RESTful-Schnittstelle verarbeitet, Formularübermittlungen verarbeitet, potenziell gefährlichen Inhalten entgeht, sich mit einer Datenbank verbindet, mit Benutzersitzungen zusammenarbeitet, um Flash-Nachrichten anzuzeigen, einen dynamischen RSS-Feed zu generieren und wie man Anwendungsfehler ordnungsgemäß behandelt.

Wenn Sie die App weiterentwickeln möchten, sollten Sie sich mit der Benutzerauthentifizierung befassen, z. B. mit dem Juwel der Sinatra-Authentifizierung.

Wenn Sie die App auf einem Webserver bereitstellen möchten, können Sie Ihre Sinatra-Anwendungen, da Sinatra mit Rake erstellt wurde, ganz einfach auf Apache- und Nginx-Servern hosten, indem Sie Passenger installieren.

Alternativ können Sie sich Heroku ansehen, eine Host-Plattform mit Git-Unterstützung, mit der Sie Ihre Ruby-Web-Apps so einfach wie git push heroku bereitstellen können (kostenlose Konten sind verfügbar!).

Wenn Sie mehr über Sinatra erfahren möchten, lesen Sie die ausführliche Readme-Datei, die Dokumentation-Seiten und das kostenlose Sinatra-Buch.

Hinweis: Die Quelldateien für jeden Teil dieser Miniserie sind zusammen mit der fertigen App auf GitHub verfügbar.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.