Juni 2016

Band 31, Nummer 6

Dieser Artikel wurde maschinell übersetzt.

Die arbeiten Programmierer - wie mittlere zu sein: Passport

Durch Ted Neward | Juni 2016

Ted NewardWillkommen Sie bei MEANers.

Ich habe eine Menge serverseitige Aufgaben durchgeführt, und es wird immer der Zeit, die zunächst auf der Clientseite Dinge über bewegen. Bevor ich dies tun, ist es eine Sache, die absolut Erörterung den Übergang vollständig machen. Insbesondere muss ich Benutzer unterstützen kann. Die meisten (wenn nicht alle zu diesem Zeitpunkt) erfordern eine Art von Benutzerauthentifizierungsverfahren Herstellen der Identität eines Benutzers, in der Regel so, dass Sie die Daten einschränken können, die angezeigt werden, oder die Optionen, mit denen sie innerhalb des Systems führen kann.

Obwohl es immer verlockend "Eigene Rollup" innerhalb der Community Knoten das ist nur so 2010! Die richtige Antwort auf solche Probleme ist immer "zu den Npm", und in diesem Fall ist die weit verbreitete Sieger um Authentifizierungssystemen eine Node.js-Bibliothek namens Passport.

Passport

Zu diesem Zeitpunkt sollte es sein, um herauszufinden, was die ersten Schritte zur Verwendung der Passport-Bibliothek sind einfach. Erfahren Sie, den Npm-Paketnamen und "Npm install". Der Paketname Npm kann online Npm Registrierung wird durchsucht, oder besuchen die Passport-Homepage ermittelt werden. Besuchen PassportJS.org zuerst ergibt sich jedoch in zwei interessante Einzelheiten:, gegen jedes andere Node.js-Paket-Homepage jemals geschrieben, der Befehl "Npm Install" nicht vorhanden direkt auf der Titelseite; ist zwei dieser Passport hat offensichtlich dieses Konzept von "Strategien", und es ist wichtig.

Der Grund dafür ist einfach: Wenn Sie b. z. "Es ist Zeit, die zum Authentifizieren der Anmeldeinformationen des Benutzers" das ist eigentlich eine vage-Anweisung. Nicht nur gibt es eine Vielzahl von unterschiedlichen Anmeldeinformationen, die zur Authentifizierung verwendet werden kann, ist mehr als tausend, oder mehrere unterschiedliche Anmeldeinformationen gespeichert (in Server), für die ein Benutzer authentifizieren kann. Passport möchte die Lösung für jede Art von Authentifizierung für jede Art von Anmeldeinformationsspeicher, Facebook, LinkedIn, Google oder Ihre eigene lokale Datenbank – und verwendet eine Vielzahl verschiedener Arten von Anmeldeinformationen, die aus Benutzername und Kennwort durch JSON Web Tokens Träger HTTP-Header und jeden beliebigen anderen, die Sie umsetzen können.

Dies bedeutet, und diese Passport-Konto nicht nur ein Paket. Ein Kern Passport-Paket vorhanden ist und Strategien (307 und tatsächlich zum Zeitpunkt der Verfassung dieses Artikels) für Passport an die eigentliche Arbeit für die Authentifizierung sind. Die Wahl der richtigen Strategie (oder Strategien, die – ich werde in Kürze) definiert das aktuelle Paket erforderlich ist, das wiederum definiert, was zu installieren. (Aber tatsächlich in Advertising Zeit hier Passport tatsächlich definiert eine Core-Pakets "Passport", die von den anderen Strategien beteiligt sind, verwendet werden, damit Sie einen Sprung auf Dinge nutzen können, wie ein "Npm install – speichern Passport", bevor ich mit der Strategie-Details beschäftigen).

Hallo, lokal

Bei weitem der am häufigsten verwendete Strategie (vor allem für Systeme, die anderen Benutzerspeichern internen Datenbanken-Anmeldeinformationen erstellt werden) ist die Strategie "local". Dies ist die klassische "sendet der Client einen Benutzernamen und ein Kennwort ein, und Sie vergleichen mit... nun, was auch immer Sie Benutzernamen und Kennwörter in speichern." Es ist wohl auch nicht annähernd so sicher wie einige der anderen Strategien, aber es ist ein guter Ausgangspunkt.

Moment im Code ich gearbeitet haben, wurde keine keinerlei Authentifizierung. Also, wir Ihre Umgebung einfach von nur hartcodieren festen Benutzername/Kennwort an. Nachdem Sie die Funktionsweise von Passport sehen, ist es relativ einfach angezeigt, in dem der Code für eine Datenbank für den Vergleich, also werde ich weglassen, die gehen würde.

Entschlossen, dass ich die Passport-Local-Strategie verwenden möchten, zunächst mit "Npm-install – speichern Passport-Local" die erforderlichen Passport direktes abrufen. (Beachten Sie, dass der "--Speichern"-Argument legt er in der Paketmanifestdatei ein, sodass es automatisch als formale Abhängigkeit nachverfolgt werden muss.)

Nach der Installation muss ich drei Dinge: one, Passport, um die Verwendung der angegebenen Strategie; konfigurieren zwei, einrichten die HTTP-URL-Route zu dem der Benutzer die Authentifizierungsanforderung gesendet wird. drei, richten Sie die Express-Middleware, bevor der Benutzer tatsächlich die URL der HTTP-Zugriff auf betreffenden Authentifizierung.

Konfiguration

Ich beginne durch Abrufen der ersten Passport, die in der Anwendung geladen. Vorausgesetzt, dass Passport und Passport-lokale bereits installiert wurden, muss ich sie laden in die Datei app.js Skript über die üblichen Magic erforderlich:

var express = require('express'),
  bodyParser = require('body-parser'),
  // ...
  passport = require('passport'),
  LocalStrategy = require('passport-local').Strategy;

Beachten Sie, dass die LocalStrategy geringfügig festgelegt ist. Wie weisen mit MongoClient vor, Sie tatsächlich LocalStrategy das Ergebnis für den Zugriff auf das Feld "Strategie" aus dem Objekt, das aus dem Aufruf zurückgegeben wird. Diese is'nt häufig in Node.js, aber es ist nicht so selten, eindeutig sein. LocalStrategy in diesem Fall dienen als eine Art von Klasse instanziiert werden soll (oder als es als JavaScript-Code in der Regel erhalten).

Ich möchte der Express-Umgebung mitteilen, dass Passport den Auftrag ist:

var app = express();
app.use(bodyParser.json());
app.use(passport.initialize());

Der Aufruf von Initialize ist ohne Erläuterung verständlich. Es wird zum Empfangen eingehende Anforderungen vorbereiten Passport vorbereiten. Es werden häufig ein ähnlichen Aufruf an passport.session pro Benutzer einrichten Sitzungen, ähnlich wie Sie in ASP.NET jedoch für eine HTTP-API wie was ich hier erstelle, die weniger oft notwendig oder wünschenswert (werde ich Ihnen dazu in Kürze).

Challenge

Als Nächstes muss ich den Rückruf einzurichten, den Passport aufgerufen wird, erhält eine Authentifizierungsanforderung. Dieser Rückruf wird die Arbeit der Benutzer gesucht werden, und überprüfen das Kennwort übergeben. (Oder in einem Szenario mit mehr reale Benutzer suchen und überprüfen, ob der Hashwert des salted Kennworts ist identisch mit den Hashwert des salted Kennworts derzeit in der Datenbank gespeichert, aber das ist eigentlich eher außerhalb des Bereichs der Passport selbst.) Erfolgt durch Aufrufen von passport.use und übergibt eine Instanz von die Strategie zum Verwenden mit dem Rückruf eingebettet, siehe Abbildung 1.

Abbildung 1 zur Festlegung des Rückrufs

passport.use(new LocalStrategy(
  function(username, password, done) {
    debug("Authenticating ",username,",",password);
    if ((username === "sa") && (password == "nopassword")) {
      var user = {
        username : "ted",
        firstName : "Ted",
        lastName : "Neward",
        id : 1
      };
      return done(null, user);
    }
    else {
      return done(null, false, { message: "DENIED"} );
    }
  }
));

Hierzu sind mehrere Schritte erforderlich. Zunächst wurde zum Zeitpunkt der Rückruf aufgerufen wird, Passport bereits der Analyse der eingehenden Anforderung und extrahieren den Benutzernamen und das Kennwort für diesen Rückruf übergeben ausgeführt. Die LocalStrategy setzt Passport, dass diese Werte über mit der Bezeichnung Username und Password-Parameter übergeben werden. (Dies ist im Aufruf zur Erstellung LocalStrategy konfigurierbar, wenn diese nicht zulässig sind.)

Zweitens ist der eigentliche Mechanismus für die Überprüfung vollständig außerhalb des Passport-zuständig. Es wird vorausgesetzt, dass die Strategien führen die Überprüfung, in diesem Fall die Strategie "local" verzögert, die ausschließlich den Anwendungscode. In diesem Beispiel vergleichen Sie nur einen hartcodierten Wert, aber in Fällen konventionelle wäre dies eine Mongo-Suche für einen Benutzer, dessen Benutzername übereinstimmen, was übergeben wurde, und dann eine Überprüfung für das Kennwort.

Schließlich wird mit den üblichen Node.js Middleware-Stil Erfolg oder Fehler signalisiert mithilfe der done-Funktion mit den Parametern übergeben, der angibt, ob der Erfolg oder Misserfolg stattgefunden. Erfolg bedeutet, dass der zweite Parameter ein Objekt ist, die in der Express-Request-Objekts platziert werden, die über die Pipeline weiter übergeben wird. Fehler kann bewirkt, dass Passport Fragen Express einen 401 (nicht autorisiert) zurückgeben, und optional die Fehlermeldung, in der Regel für "flash" Nachrichten anhand der Benutzeroberfläche verwendet. (Wenn flash Nachrichten nicht verwendet werden, wird die Nachricht effektiv sofort ausgelöst.)

Folgen

Nun, übrig bleibt, konfigurieren Sie die Route mit dem die Authentifizierung erfolgt:

app.post('/login',
  passport.authenticate('local', { session: false }),
  function(req, res) {
    debug("user ", req.user.firstName, " authenticated against the system");
    res.redirect("/persons");
  });

Passport nicht besonders wichtig ist, was das URL-Muster ist, dass die eigentliche Authentifizierung ausführt; "/ Login" ist lediglich eine Konvention, aber /signin oder /user/auth oder alle ein halbes Dutzend anderer Sorten vollständig sinnvoll wäre. Der Schlüssel ist, dass der erste Schritt beim Auflösen von dieser Route besteht im Aufrufen des Passport authentifizieren, Funktion, welche Strategie zu (local) verwenden, ob das Verwendung pro Benutzer Sitzungscookies (d. h. wie bereits erwähnt, nicht besonders geeignet für eine API) übergeben, und die aktuelle Funktion aufgerufen werden, wenn die Authentifizierung erfolgreich war. Hier die Funktion protokolliert eine Meldung zum Debuggen und anschließend leitet der Benutzer die Liste der Personen in der Datenbank gespeichert.

Jetzt kann ich dies durch die Übergabe entweder Inhalt Formular bereitgestellt oder per in JSON-Inhalte testen; Da es sich um eine API handelt, ist es wahrscheinlich besser und einfacher in einem JSON-Paket gesendet:

{ "username" : "sa" , "password" : "nopassword" }

Wenn Benutzername und Kennwort übereinstimmen, Erfolg und eine 302-Umleitung an /persons zurückgegeben. Wenn dies nicht der Fall ist, klicken Sie dann eine 401-Antwort zurück übergeben wird. Es funktioniert!

Umleiten von Datenverkehr

Tatsächlich ist es ein allgemeines Muster (bei eine herkömmlichen serverseitige Web-app mit Express erstellen) aus, dass eine erfolgreiche Authentifizierung den Benutzer zu einer bestimmten route's während ein Fehlers sollte den Benutzer auf eine neue Seite, und aus diesem Grund Passport ermöglicht ein einfacher Ansatz zur Authentifizierung Rückrufe:

app.post('/login',
  passport.authenticate('local', { successRedirect: '/',
                                   failureRedirect: '/login',
                                   failureFlash: true })
);

Hier bei Erfolg Passport automatisch leitet an die URL "/", und bei einem Fehler an die "/ Login"-URL und (in diesem Fall) mit einem flash-Meldung angezeigt, dass der Benutzer konnte nicht erfolgreich angemeldet haben.

Im Fall einer API ist es üblich, weitergeben, die eine JSON-Darstellung des Benutzerobjekts zurück an dem Client für die Anzeige und Bearbeitung. Beachten Sie jedoch, die nichts sicherheitsbezogene oder vertraulich jemals wieder im Rahmen dieser gesendet werden soll, keine Kennwörter, insbesondere. Der Browser sind alle sehr hilfreich bei der Bereitstellung von clientseitigen debugging-Dienstprogramme, und ein Angreifer könnte daher sehr einfach erreichen, in das Benutzerobjekt im Arbeitsspeicher und Start Bearbeitung sofort auf ihre Geschmack des Browsers gespeichert. Das ungültige wäre. (Diese JSON-Objekte können auch "in Bearbeitung" Aufforderung am Node.js-basierte API-Systeme, die über HTTPS statt über HTTP ausgeführt manipuliert werden. Glücklicherweise meistens, Konfigurieren von Express über HTTPS anstelle von HTTP ist mehr eine Übung in der Cloud-Konfiguration als eine programmgesteuerte Änderung.) Daher Kennwörter lassen sich nie auf den Server, und "Rollen" (für ein System rollenbasierte Autorisierung) immer aus der Datenbank nicht aus dem übergebenen die Anforderung überprüft werden soll.

Wie bereits beschrieben, jedoch jetzt der API-Client-Authentifizierung übertragen muss Anmeldeinformationen jedes Mal die "/ Login" Route erreicht wird, und die Anmeldeinformationen werden nicht auf einem beliebigen anderen Routen überprüft. Während ich sicherlich können Authentifizierung überprüft jede Route einfügen (und sollten, können sie sich vorstellen stammen) soll nicht die Anmeldeinformationen als Teil jeder Methodenaufruf zu übergeben.

Alternativen

Passport hat diese Idee "in gebeten," behandelt, wie sie sagen.

Erstens können Sie immer zurückkehren, um Sitzungen einschalten; Wenn Sitzungen aktiviert sind, wird Passport erstellen, einen eindeutigen Bezeichner und dies als Teil der HTTP-Antwort als Cookie zurückzugeben. Clients sind erforderlich, damit das Cookie als Teil der jede nachfolgende Anforderung zurück übergeben. Die wichtigste Anforderung an diesem Punkt auf der Serverseite ist, dass die Passport-Bibliothek muss wissen, wie Sie ein Objekt in einen Bezeichner umzuwandeln und wieder zurück. Sie rufen diese serialisieren und Deserialisieren von einem Benutzer und erfordert einrichten Methoden-Callbacks für jede dieser beiden Passport-Endpunkte:

passport.serializeUser(function(user, done) {
  done(null, user.id);
});
passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user);
  });
});

Die SerializeUser-Funktion bietet einen eindeutigen Bezeichner für den Benutzer Passport (sodass ich es aus dem Feld user.id grab) und die DeserializeUser-Funktion ist die Umkehrung (, weshalb ich die Id als Primärschlüssel in einer Datenbanksuche für das Benutzerobjekt als Ganzes übergeben).

Sie aktivieren können Sitzungen für die meisten, wenn nicht alle Passport-Strategien, aber im Allgemeinen es funktioniert, wenn generiert, der Server HTML direkt vom Browser interpretiert werden. APIs in der Regel nicht für die Arbeit mit Cookies fast so viel, besonders da APIs durch systemeigene mobile app-Clients wie oder öfter als ein Browser-basierter Client oft erreicht werden.

Ein zweiter Ansatz verwendet eine andere Passport-Strategie, die "bekannten geheimer Schlüssel" für Client und Server verwendet. Dies kann dann in einer Vielzahl von Methoden übergeben werden. In einigen Fällen das System verwaltet einen bekannten Satz von ausgestellten "API-Schlüssel", und geben Sie den Schlüssel als Teil der jeweiligen Anforderung. Dies ist häufig mit einer Reihe von REST-Diensten von Drittanbietern trägt ein Sicherheitsproblem, wenn ein Angreifer den Schlüssel abrufen kann, die Angreifer als der Client auftreten kann, bis der Client den Schlüssel zurücksetzt. Passport bietet eine Strategie für diese; Verwenden Sie "Npm install – speichern Passport-Localapikey." Das Verhalten ähnlich wie die lokalen-Strategie, wobei jetzt die Authentifizierungsmethode für die Strategie der API-Schlüssel in der Datenbank statt des Benutzernamens und Kennworts nachschlagen.

Ein ähnlicher Ansatz macht die Verwendung von JSON Web Tokens (Jwt), sind sicherer, aber eine viel mehr Platz erfordern erläutern als hier ich habe; "Npm-install – speichern Passport-Jwt" werden in das Projekt. JWTs sind ein gepackter Satz an eine Vielzahl von verschiedenen Datenelementen, von denen kann ein gemeinsamer geheimer Schlüssel (à la API-Schlüssel oder Kennwort), aber vor bestimmten Aussteller, Zielgruppe und mehr überprüft werden kann.

Oder vielleicht das Ziel keine Art von Anmeldeinformationen zu speichern, sondern Drittanbieter-Systemen (z. B. Facebook, Google, Twitter, LinkedIn oder mehrere hundert andere beliebte Sites) dazu die Authentifizierung abhängig ist. Passport ist hier behandelt, auch mit bestimmten Strategien für jede dieser einzeln, als sowie allgemeine OAuth 2.0 (und OpenID, für die Websites, die die verwenden) Strategien Standorte.

Meiner Meinung nach der Punkt löschen aufgefüllt wird: Wenn Sie ein Authentifizierungssystem vorstellen können, wird Passport bereits definiert. Einfach "Npm install," richten Sie die Konfiguration den Authorize-Aufruf in den Express-Routen eingefügt, und schon sind Sie startklar.

Übrigens, scheint es wichtig, darauf hinzuweisen, dass Dienste vorhanden sind, über das Internet, die nur einen von Access Control für alle diese Authentifizierungsprobleme bereitstellt. Diese Dienste "Authentifizierung-as-a-Service" werden immer häufiger als die Anzahl der Websites, mit denen Leute in regelmäßigen Abständen angelegt und von einem administrativen Kopfschmerzen werden. Zu meinen Favoriten, Auth0 (das tatsächlich ein paar Ex-Microsoft-Entwicklern im technischen Bereich des Unternehmens hat), wird ein Sponsor für die Passport-Projekt und die Symbole und Logos diskrete zahllosen der Passport-Website angezeigt. Ich empfehle dringend, Auschecken, wenn das Projekt noch nicht auf eine vorher festgelegte Authentifizierungsstrategie vorhanden (z. B. ein Legacysystem oder Integration mit Facebook oder Dropbox oder was auch immer).

Nachbereitung

Passport ist wohl der erfolgreichen Authentifizierung-Projekten, die je entwickelt wurde, über eine Sprache oder Plattform. Es verwaltet, geben Sie die erforderliche Authentifizierung "Hooks" geöffnetem tatsächliche Mittel für die Authentifizierung bei, die steuern möchten noch verzögern und alle diese Aufgaben ausführen, wenn Sie nicht. Die Strategie-Ansatz bedeutet es beliebig erweitern, und jede Art von neuen Authentifizierungsschema, das, sogar 20 Jahren in die Zukunft entstehen möglicherweise, aufnehmen kann. (Nicht lachen – alle diese JavaScript, tatsächlich weiterhin 20 Jahren ab sofort ausgeführt werden. Sie überwachen.)

Aber Passport ist fast so viel von was es nicht als Funktion definiert. es vollständig auf jede Idee rollenbasierte Autorisierung Pfund, und es wird nicht versucht, jede Art von Verschlüsselung oder Kryptographie Adresse. Passport dreht sich alles Anmeldeinformationen überprüfen, natürlich von diesem Punkt ist der Name, der viel klarer – genau wie ich in Europa auf Reisen, ich mein Passport-Konto möchte, um nachzuweisen, dass mir ein American Bürger anzeigen, Passport erfordert, dass Benutzer ihre Anmeldeinformationen angezeigt, sodass sie nachweisen können sie Bürgern gutem innerhalb des Systems sind.

Wieder auffindbar selbst nicht genügend Speicherplatz und Zeit, daher jetzt... viel Spaß beim Programmieren!


Ted NewardPolytechnology Seattle basierende Berater, Referent und Mentor. Er hat hat mehr als 100 Artikel geschrieben, ist ein F#-MVP und verfasst und Mitautor ein Dutzend Bücher. Sie erreichen ihn unter ted@tedneward.com. Wenn Sie möchten, dass er die Zusammenarbeit mit Ihrem Team, oder Lesen Sie seinen Blog unter blogs.tedneward.com.

Dank den folgenden technischen Experten für die Überprüfung dieses Artikels: Shawn Wildermuth