Co robi oprogramowanie pośredniczące passport.session ()?

125

Buduję system uwierzytelniania przy użyciu Passport.js przy użyciu Easy Node Authentication: Setup i Local tutorial .

Nie wiem, co passport.session()robi.

Po zabawie z różnymi programami pośredniczącymi zrozumiałem, że express.session()to właśnie wysyła identyfikator sesji za pośrednictwem plików cookie do klienta, ale nie wiem, co passport.session()robi i dlaczego jest dodatkowo wymagane express.session().

Oto jak skonfigurowałem swoją aplikację:

// Server.js konfiguruje aplikację i konfiguruje serwer WWW

//importing our modules
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');

var configDB = require('./config/database.js');

//Configuration of Databse and App

mongoose.connect(configDB.url); //connect to our database

require('./config/passport')(passport); //pass passport for configuration

app.configure(function() {

    //set up our express application

    app.use(express.logger('dev')); //log every request to the console
    app.use(express.cookieParser()); //read cookies (needed for auth)
    app.use(express.bodyParser()); //get info from html forms

    app.set('view engine', 'ejs'); //set up ejs for templating

    //configuration for passport
    app.use(express.session({ secret: 'olhosvermelhoseasenhaclassica', maxAge:null })); //session secret
    app.use(passport.initialize());
    app.use(passport.session()); //persistent login session
    app.use(flash()); //use connect-flash for flash messages stored in session

});

//Set up routes
require('./app/routes.js')(app, passport);

//launch
app.listen(port);
console.log("Server listening on port" + port);
Georges Krinker
źródło

Odpowiedzi:

139

passport.session() działa jako oprogramowanie pośredniczące, które zmienia obiekt req i zmienia wartość „user”, która jest obecnie identyfikatorem sesji (z pliku cookie klienta) na prawdziwy deserializowany obiekt użytkownika.

Podczas gdy inne odpowiedzi zawierają kilka dobrych punktów, pomyślałem, że można podać bardziej szczegółowe informacje.

app.use(passport.session());

jest równa

app.use(passport.authenticate('session'));

Gdzie „sesja” odnosi się do następującej strategii, która jest dołączona do programu paszsportJS.

https://github.com/jaredhanson/passport/blob/master/lib/strategies/session.js

Konkretnie linie 59–60:

var property = req._passport.instance._userProperty || 'user';
req[property] = user;

Gdzie zasadniczo działa jako oprogramowanie pośredniczące i zmienia wartość właściwości „user” w obiekcie req, aby zawierał zdeserializowaną tożsamość użytkownika. Aby to działało poprawnie, musisz uwzględnić serializeUseri deserializeUserfunkcje w swoim kodzie niestandardowym.

passport.serializeUser(function (user, done) {
    done(null, user.id);
});

passport.deserializeUser(function (user, done) {
    //If using Mongoose with MongoDB; if other you will need JS specific to that schema.
    User.findById(user.id, function (err, user) {
        done(err, user);
    });
});

Spowoduje to znalezienie właściwego użytkownika z bazy danych i przekazanie go jako zmiennej zamykającej do wywołania zwrotnego, done(err,user);dzięki czemu powyższy kod w passport.session()obiekcie req może zastąpić wartość „user” w obiekcie req i przekazać do następnego oprogramowania pośredniego w stosie.

lindsaymacvean
źródło
hej, jak mogę przechowywać dane użytkownika tylko w sesji Nie chcę przechowywać ich bezpośrednio w bazie danych
Newbiee
1
„w nagłówkach żądań”? nie tylko w
żądanym
Zauważyłem, że jeśli strategia sesji jest w stanie przywrócić autoryzację i deserializować użytkownika. Ale mimo to uwierzytelnianie nadal przechodzi do następnej strategii, którą w moim scenariuszu jest autoryzacja na Facebooku. Zastanawiam się, jaki jest sens strategii sesji, jeśli nadal wywołuje następujące strategie, nawet jeśli sesja jest w stanie odzyskać użytkownika.
nishant
15

Z dokumentacji

W aplikacji opartej na Connect lub Express do zainicjowania usługi Passport wymagane jest oprogramowanie pośredniczące passport.initialize (). Jeśli aplikacja korzysta z trwałych sesji logowania, należy również użyć oprogramowania pośredniczącego passport.session ().

i

Sesje

W typowej aplikacji internetowej poświadczenia używane do uwierzytelniania użytkownika będą przesyłane tylko podczas żądania logowania. Jeśli uwierzytelnienie powiedzie się, sesja zostanie ustanowiona i utrzymywana za pośrednictwem pliku cookie ustawionego w przeglądarce użytkownika.

Każde kolejne żądanie nie będzie zawierało poświadczeń, ale raczej unikalny plik cookie identyfikujący sesję. Aby obsługiwać sesje logowania, Passport będzie serializować i deserializować wystąpienia użytkowników do i z sesji.

i

Należy pamiętać, że włączenie obsługi sesji jest całkowicie opcjonalne, chociaż jest zalecane w przypadku większości aplikacji. Jeśli jest włączona, użyj express.session () przed passport.session (), aby upewnić się, że sesja logowania zostanie przywrócona w prawidłowej kolejności.

Josh C.
źródło
1
Dziękuję za szybką odpowiedź, ale to nie odpowiada na moje pytanie. Pamiętaj również, że jeśli masz aplikację ekspresową i używasz express.session (), na dowolnym kliencie, który łączy się z Twoim serwerem ekspresowym (niezależnie od tego, czy jest uwierzytelniony, czy nie), sesja zostanie mu przydzielona za pośrednictwem pliku cookie. Jest to niezależne od tego, czy znajduje się na chronionej logowaniem stronie Twojej aplikacji, czy nie. Nadal chciałbym poznać różnicę między obydwoma programami pośredniczącymi.
Georges Krinker
1
@GeorgesKrinker to metody serializeUser () i deserializeUser. Ekspresowe oprogramowanie pośredniczące przywróci informacje o sesji, ale niekoniecznie ma to związek ze sposobem zarządzania danymi użytkownika przez paszport. Należy to zrobić po ponownym nawodnieniu sesji ekspresem.
Josh C.
Cóż, miałem wrażenie, że metody serializeUser () i deserializeUser działają w ramach routingu w trybie authentication ().
Georges Krinker
@GeorgesKrinker Nie sądzę. Kiedy korzystałem z paszportu, dzwoniłem tylko do .authenticate podczas logowania.
Josh C.
app.post('/login', passport.authenticate('local'), ...
Josh C.
11

Chociaż będziesz używać PassportJsdo sprawdzania poprawności użytkownika jako części adresu URL logowania, nadal potrzebujesz mechanizmu do przechowywania tych informacji o użytkowniku w sesji i pobierania ich przy każdym kolejnym żądaniu (tj. Serializacji / deserializacji użytkownika).

W efekcie uwierzytelniasz użytkownika przy każdym żądaniu, nawet jeśli to uwierzytelnienie nie musi wyszukiwać bazy danych ani Oauth, jak w odpowiedzi logowania. Dlatego paszport będzie traktował uwierzytelnianie sesji również jako kolejną strategię uwierzytelniania.

Aby skorzystać z tej strategii - która nosi nazwę session, wystarczy użyć prostego skrótu - app.use(passport.session()). Należy również zauważyć, że ta konkretna strategia będzie wymagać zaimplementowania funkcji serializacji i deserializacji z oczywistych powodów.

uniwalker
źródło
11

Po prostu uwierzytelnia sesję (którą wypełnia express.session()). Odpowiada:

passport.authenticate('session');

jak widać w kodzie tutaj:

https://github.com/jaredhanson/passport/blob/42ff63c/lib/authenticator.js#L233

Jared Hanson
źródło
6
Co masz na myśli? Jest uruchamiany przy każdym żądaniu i niekoniecznie ma żadnych poświadczeń do uwierzytelnienia. Czy mógłbyś podać mi trochę więcej szczegółów na temat przepływu pracy, który ma miejsce przy każdym żądaniu?
Georges Krinker
6
Tak, jest uruchamiany na każde żądanie. Identyfikator sesji generowany przez Express jest unikalnym identyfikatorem, który jest w przybliżeniu odpowiednikiem tokenu uwierzytelniającego wysyłanego przez przeglądarkę z każdym żądaniem. Dane przechowywane w tej sesji służą do przywrócenia stanu uwierzytelnienia użytkownika.
Jared Hanson,
Witaj @JaredHanson Czy mógłbyś rzucić okiem na to . Nigdzie nie mogłem znaleźć odpowiedzi?
Saras Arya
@JaredHanson Próbuję użyć passport.js do uwierzytelnienia na powszechnie używanym serwerze autoryzacji typu open source, który jest zgodny z OAuth2. Ale pojawia się błąd. Czy chcesz pomóc rozwiązać problem? Oto link: stackoverflow.com/questions/38176236/…
DollarCoffee
@JaredHanson: Zauważyłem, że obiekt req rozszerzony o informacje passport.user zaraz po zalogowaniu się przez google-oauth, zostaje utracony, gdy kolejne żądanie nowej strony jest wykonywane w witrynie. Czy to oczekiwane zachowanie? W takim razie nie wiem, jak odzyskać informacje o ostatnio zalogowanym użytkowniku?
user1102171