Giugno 2016

Volume 31 Numero 6

Il presente articolo è stato tradotto automaticamente.

Il lavoro programmatore - come essere media: Passport

Da Ted Neward | Giugno 2016

Ted NewardBentornato, MEANers.

Applico questo una considerevole quantità di lavoro sul lato server e si sta avvicinando l'ora in cui iniziare lo spostamento su alla fine delle operazioni client. Prima di procedere, tuttavia, è assolutamente necessario illustrare prima di rendere la transizione interamente un altro aspetto. In particolare, è necessario essere in grado di supportare gli utenti. La maggior parte delle applicazioni (se non tutti gli elementi, a questo punto) richiedono un tipo di meccanismo di autenticazione utente per stabilire l'identità di un utente, in genere in modo che sia possibile limitare i dati contenenti le o le opzioni che consente loro di svolgere all'interno del sistema.

Mentre si è sempre tentati di "implementarne uno personalizzato," all'interno della community di nodo, che è semplicemente così 2010! La risposta giusta a uno di questi tipi di forniranno è sempre "Vai alle npm" e in questo caso, il vincitore discesa mani generalizzato attorno a sistemi di autenticazione è una libreria Node. js chiamata Passport.

Passport

Da questo punto, dovrebbe essere semplice capire quali sono i primi passaggi per l'utilizzo della libreria di Passport. trovare il nome del pacchetto npm e "installare npm". Il nome del pacchetto npm può essere individuato eseguendo una ricerca nel Registro di sistema npm online o visitando la home page di Passport. Tuttavia, prima visita PassportJS.org produce due Mariani interessanti: uno, che contrariamente a ogni altra Node. js pacchetto home page mai scritta, il comando "npm install" non è presente qui della pagina anteriore. due, tale Passport è apparentemente il concetto di "strategie" ed è importante.

Il motivo è semplice: Quando pronuncia, "è possibile autenticare le credenziali dell'utente," che è effettivamente un'istruzione imprecisi. Non solo esiste una serie di credenziali diverse che potrebbero essere utilizzati per autenticare, sussiste delle migliaia o più credenziali vengono archiviati (in stile server) in cui un utente potrebbe eseguire l'autenticazione. Passport vuole essere la soluzione a qualsiasi tipo di autenticazione a fronte di qualsiasi tipo di archivio di credenziali, Facebook, LinkedIn, Google o database locale e utilizza una varietà di tipi diversi di credenziali, dal nome utente/password tramite token Web JSON per le intestazioni di trasporto HTTP e altro ancora che è possibile che da sogno backup.

Ciò significa, quindi, il Passport non è un solo pacchetto. è un pacchetto di passport core e quindi sono disponibili strategie (307 di esse, infatti, al momento della stesura di questo articolo) per la modalità Passport per svolgere il lavoro effettivo di autenticazione. La scelta della strategia (o strategie, verrà spiegato che in un momento) definisce i pacchetti effettivi necessari, che a sua volta definisce gli elementi da installare. (Ma la verità in pubblicità ora qui, Passport definire in realtà un pacchetto di base "passport" che verrà utilizzato da altre strategie coinvolti, è possibile ottenere un salto su elementi effettuando un "npm install - Salva passport" prima di esplorare i dettagli di strategia).

Ciao, locale

Strategia indubbiamente più comune (in particolare per sistemi creati con gli archivi di database/credenziali utente interno) sono la strategia "locale". Questa è la classica, "Client invia un nome utente e una password e lo si confronta con... Beh, qualsiasi archiviare nomi utente e password in." È probabilmente anche non altrettanto sicuro quanto alcune delle altre strategie, ma è un buon punto di partenza.

Attualmente, nel codice ho lavorato con, sono non stati alcuna autenticazione. Pertanto, possibile semplificare le operazioni da solo a livello di codice un nome utente/password fisso sul posto. Dopo aver visualizzato il funzionamento di Passport, è relativamente semplice visualizzare il codice per una ricerca nel database in cui verrebbero per il confronto, quindi faccio di tralasciare che.

Avendo deciso che si desidera utilizzare la strategia di passport locale, iniziare con "npm install - Salva passport locale" per ottenere i bit necessari passport sul posto. (Tenere presente che il "-salvare" argomento lo inserisce nel file manifesto del pacchetto in modo che sarà vengono rilevata automaticamente come dipendenza formale.)

Una volta installato, è necessario eseguire tre operazioni: 1, configurare Passport per utilizzare la strategia specificata; due, la route URL HTTP a cui l'utente invierà la richiesta di autenticazione. tre, configurare il middleware Express per richiedere l'autenticazione prima di consentire all'utente di accedere in realtà l'URL HTTP in questione.

Configurazione

Per iniziare, ottenere prima Passport il caricamento dell'applicazione. Supponendo che sono già stati installati passport e passport locale, è necessario caricarli nel file app. js script tramite le normali richiede magic:

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

Si noti che il LocalStrategy è leggermente diversa. come con MongoClient prima, effettivamente assegnare LocalStrategy il risultato dell'accesso al campo "Strategia" dell'oggetto restituito dalla chiamata di richiesta. Questo is'nt comuni in Node. js, ma non è raro in modo da essere univoco. LocalStrategy in questo caso sta per essere utilizzato come un tipo di classe per creare un'istanza (o come vicino come JavaScript possono in genere get).

È inoltre necessario stabilire l'ambiente di Express che Passport è attivato il processo:

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

La chiamata di inizializzazione è facilmente comprensibile; verrà Prepara Passport per prepararsi alla ricezione di richieste in ingresso. Spesso, verrà essere una simile chiamata a passport.session per configurare le sessioni, simile a quella indicata in ASP.NET, ma per un'API HTTP come ciò che si sta sviluppando in questo caso, che è meno spesso necessario o opportuno per utente (parlerò che tra poco).

La sfida

Successivamente, è necessario stabilire il callback che verrà richiamato Passport quando riceve una richiesta di autenticazione. Questo callback eseguirà l'operazione di ricerca l'utente e convalida la password passati. (O, in uno scenario più del mondo reale, cercare l'utente e la convalida che l'hash della password con salting corrisponde all'hash di password con salt attualmente archiviati nel database, ma è molto più all'esterno dell'ambito di Passport stesso.) Questa operazione chiamando passport.use e passando un'istanza della strategia da utilizzare, con il callback incorporato all'interno di esso, come illustrato nella Figura 1.

Figura 1 stabilisce il Callback

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"} );
    }
  }
));

Alcune operazioni sono in corso. In primo luogo, al momento che il callback viene richiamato, Passport ha già eseguito le operazioni di analisi di richiesta in ingresso e l'estrazione e il nome utente e la password di passare a questo callback. Per LocalStrategy, Passport presuppone che tali valori vengono passati tramite i parametri denominati nome utente e password, rispettivamente. (Questo è configurabile nella chiamata di costruzione LocalStrategy se quelli non accettabili).

In secondo luogo, il meccanismo effettivo di verifica è completamente all'esterno di giurisdizione Passport; si presuppone le strategie eseguirà la verifica e in questo caso, la strategia di "locale" rinvia che completamente al codice dell'applicazione. In questo esempio, è sufficiente controllare rispetto a un valore hardcoded, ma in casi più convenzionali sarebbe una ricerca Mongo per un utente il cui nome utente corrisponde a ciò che è stato passato e quindi un controllo con la password.

In terzo luogo, in conformità con lo stile del middleware Node. js consueto, esito positivo o negativo viene segnalato dall'utilizzo della funzione done, con i parametri passati che indica se ha avuto luogo esito positivo o negativo. Esito positivo indica che il secondo parametro è un oggetto utente che verrà inserito all'interno dell'oggetto richiesta di Express che viene passato più avanti nella pipeline; errore causerà Passport chiedere Express per restituire una risposta 401 (non autorizzato) e può includere facoltativamente il messaggio di errore, in genere utilizzato per i messaggi "flash" con l'interfaccia utente. (Se non vengono utilizzati messaggi flash, il messaggio viene effettivamente eliminato.)

Conseguenze

A questo punto, non rimane che configurare la route da cui verrà eseguita l'autenticazione:

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

In particolare non si preoccupa di Passport che cos'è il modello di URL che consente di eseguire l'autenticazione effettiva; /login è semplicemente una convenzione, ma /signin o /user/auth o uno qualsiasi di una mezza dozzina altre varietà sarebbe ragionevole interamente. La chiave è che il primo passaggio durante la risoluzione di questo percorso consiste nel chiamare passport l'autenticazione di funzione, passando la strategia da utilizzare (local), se i cookie di sessione per utente utilizzare (che, come già indicato, non è particolarmente appropriato per un'API) e la funzione effettiva da richiamare se l'autenticazione ha esito positivo. In questo caso, la funzione registra semplicemente un messaggio per eseguire il debug e reindirizza l'utente all'elenco di persone archiviati nel database.

A questo punto, è possibile testare questo passando entrambi contenuto inviato al form o mediante l'invio di contenuto JSON. Poiché si tratta di un'API, è probabilmente migliore e più facile da inviare in un pacchetto JSON:

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

Se il nome utente e la password corrisponde, esito positivo e un reindirizzamento 302 al /persons verrà restituito. in caso contrario, quindi una risposta 401 viene restituito. Funziona!

Il reindirizzamento del traffico

In effetti è un modello comune (quando si compila un'app di Web sul lato server tradizionale con Express) che il completamento dell'autenticazione richiederà all'utente di una route specificata, considerando che un errore deve richiedere all'utente di una nuova pagina e per questo motivo, Passport consente un approccio più semplice per l'autenticazione della callback:

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

In questo caso, in caso di riuscita, Passport reindirizzerà automaticamente per l'URL "/" e in caso di errore, di "/ account di accesso" URL, e, in questo caso, con un messaggio lampeggiante che indica che l'utente non è riuscito a eseguire correttamente l'accesso.

Nel caso di un'API, tuttavia, è più comune a restituire una rappresentazione JSON dell'oggetto utente per il client per la visualizzazione e modifica. Tenere presente, tuttavia, che non correlato alla sicurezza o sensibili devono essere mai inviato come parte di questo oggetto, ovvero nessuna password, in particolare. I browser sono tutti molto utili per fornire alle utilità di debug lato client e di conseguenza, qualsiasi utente malintenzionato potrebbe raggiungere molto facilmente in quell'oggetto utente mantenuto nella memoria del browser e inizio modifica assente per i relativi contenuti. Che potrebbe essere danneggiato. (Questi oggetti JSON possono anche essere alterati "in volo," che richiede più Node. js sistemi basati su API per l'esecuzione in HTTPS anziché HTTP. Fortunatamente, la maggior parte dei casi, la configurazione Express per l'esecuzione su HTTPS anziché HTTP è più un esercizio nella configurazione cloud rispetto a qualsiasi modifica a livello di codice.) Di conseguenza, le password non devono lasciare mai il server e "ruoli" (per un sistema di autorizzazione basata sui ruoli) devono essere sempre selezionati del database, non dall'oggetto utente che di richiesta passati.

Come è scritto, tuttavia, ora sarà necessario passare l'autenticazione il client API credenziali ogni volta che il "/ account di accesso" route viene raggiunto, e le credenziali non verranno controllate in uno qualsiasi di altre route. Mentre certamente possibile inserire controlli di autenticazione in ogni route e deve provenire considerare questa operazione, probabilmente non desidero passare le credenziali come parte di ogni chiamata al metodo.

Alternative

Passport ha questa idea trattata ""spades, come si dice.

In primo luogo, è sempre possibile tornare ad attivare sessioni; Quando si trovano in sessioni, Passport creerà un identificatore univoco e mano nuovamente come parte della risposta HTTP come un cookie. I client devono quindi tale cookie a restituire come parte di ogni richiesta successiva. Il requisito principale a questo punto sul lato server è che la libreria Passport deve sapere come trasformare un oggetto utente in un identificatore e viceversa; chiamano la serializzazione e deserializzazione di un utente e richiede l'impiego di callback dei metodi per ognuno di questi due endpoint Passport:

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

La funzione serializeUser è progettata per fornire un identificatore univoco per l'utente a Passport (in modo recuperarle fuori dal campo user.id) e la funzione deserializeUser esegue l'operazione inversa (in modo da utilizzare l'id passato come chiave primaria in una ricerca nel database per l'oggetto utente nel suo complesso).

È possibile attivare sessioni per la maggior parte, se non tutte, le strategie di Passport, ma in genere che funziona quando il server generi HTML deve essere interpretato direttamente dal browser. API non tendono a lavorare con i cookie quasi quanto, in particolare in quanto spesso raggiunti API dai client di app native per dispositivi mobili quanto o più spesso di un client basato su browser.

Un altro approccio utilizza una diversa strategia di Passport che si basa su un segreto"noto" al client e server. Può quindi essere passato in diversi modi. In alcuni casi, il sistema gestisce un set noto di emesso "chiavi API" e tale chiave è necessario fornire come parte di ogni richiesta. Questa operazione è piuttosto comune con un numero di servizi REST di terze parti, ma vale la pena una grave vulnerabilità che se un utente malintenzionato riesce a ottenere la chiave, l'autore dell'attacco può mascherarsi fino a quando il client reimposta la chiave. Passport offre una strategia per questo oggetto. Utilizzare il comando "npm install - Salva passport localapikey." Si comporta molto esattamente come la strategia locale, ma ora il metodo di autenticazione strategia cercherà la chiave dell'API del database, anziché il nome utente e password.

Un approccio simile viene utilizzato JSON Web Tokens (Jwt), che sono più sicure, ma richiede uno spazio molto più tempo per spiegare rispetto a ciò che ho qui. "npm install - Salva passport jwt" viene visualizzato nel progetto. Jwt sono un set di un'ampia gamma di elementi di dati diversi, uno dei quali può essere un segreto condiviso (à la API chiave o password), ma può essere verificato rispetto particolari autorità emittenti, pubblico e altro ancora compresso.

In alternativa, ad esempio, l'obiettivo consiste nel non memorizzare qualsiasi tipo di credenziali affatto, ma si basano su sistemi di terze parti (ad esempio Facebook, Google, Twitter, LinkedIn o uno qualsiasi dei numerosi centinaia più diffusi siti) per eseguire l'autenticazione. Passport è trattata in questo argomento, nonché, con strategie specifiche per ognuno di questi siti singolarmente, come anche come generalizzato OAuth 2.0, OpenID, per i siti che utilizzano tale, strategie.

Credo che il punto diventando sempre più evidente: Se è possibile immaginare un sistema di autenticazione, Passport ha una strategia già definita. Solo "npm install," impostare la configurazione, inserire la chiamata autorizza le route di Express e off go.

Per inciso, sembra importante sottolineare che esistono servizi su Internet che fornisce un singolo punto di controllo di accesso per tutti questi problemi di autenticazione. Questi servizi "Autenticazione-as-a-Service" stanno diventando più diffusi come il numero di siti che gli utenti utilizzano regolarmente proliferazione e diventa più e più di un incubo amministrativo. Uno dei miei Preferiti, Auth0 (che ha effettivamente alcune persone ex Microsoft nel lato tecnico della società), uno sponsor per il progetto di Passport e le icone e i logo essere discreta sparsi in tutto il sito di Passport. Sarebbe un'ottima estrarlo se il progetto non dispone già di una strategia di autenticazione predeterminate sul posto (ad esempio un sistema legacy o l'integrazione con Facebook o Dropbox o quali sono stati).

Avvolgendo

Passport è probabilmente i più efficace progetti autenticazione mai sviluppati in qualsiasi linguaggio o piattaforma. Gestisce fornire l'autenticazione necessaria "hook" durante lasciare aperti i mezzi effettivi per l'autenticazione quando si desidera controllare che, ancora slittamento e l'esecuzione di tutto il lavoro sporco quando non è. L'approccio strategia significa il discorso all'infinito e può contenere qualsiasi tipo di nuovo schema di autenticazione che potrà emergere, anche 20 anni nel futuro. (Non-tutti questo codice JavaScript, infatti, ancora eseguire 20 anni da adesso. Guarda.)

Ma viene definito Passport quasi quanto da quello che non come azione. completamente punts su qualsiasi idea di autorizzazione basata sui ruoli e non tenti di risolvere qualsiasi tipo di crittografia o la crittografia. Passport riguarda esclusivamente il controllo, le credenziali che naturalmente da questo punto rende molto più chiaro il nome, come quando passano in Europa, è necessario visualizzare il profilo passport per dimostrare che sono un cittadino American, Passport richiede che gli utenti visualizzare le proprie credenziali in modo che risulti sono cittadini in regola all'interno del sistema.

Ancora una volta, mi considero fuori spazio e tempo, in tal caso, per ora... buona codifica!


Ted Newardè un consulente polytechnology basato su Seattle, relatore e mentore. Egli ha scritto oltre 100 articoli, è un MVP di F # e ha creato e coautore di numerosi libri. Contattarlo all'indirizzo ted@tedneward.com. Se si è interessati a far lui provenire collaborano con il team o leggere il suo blog all'indirizzo blogs.tedneward.com.

Grazie all'esperto tecnica seguente per la revisione di questo articolo: Shawn Wildermuth