Apa yang dilakukan middleware passport.session ()?

125

Saya membangun sistem otentikasi menggunakan Passport.js menggunakan Autentikasi Node Mudah: Penyiapan dan tutorial Lokal .

Saya bingung mau ngapain passport.session().

Setelah bermain-main dengan middleware yang berbeda, saya memahami bahwa express.session()itulah yang mengirimkan ID sesi melalui cookie ke klien, tetapi saya bingung tentang apa passport.session()dan mengapa itu diperlukan sebagai tambahan express.session().

Berikut adalah cara saya menyiapkan aplikasi saya:

// Server.js mengonfigurasi aplikasi dan menyiapkan server web

//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
sumber

Jawaban:

139

passport.session() bertindak sebagai middleware untuk mengubah objek req dan mengubah nilai 'pengguna' yang saat ini merupakan id sesi (dari cookie klien) menjadi objek pengguna deserialisasi yang sebenarnya.

Sementara jawaban lain membuat beberapa poin bagus, saya pikir beberapa detail yang lebih spesifik dapat diberikan.

app.use(passport.session());

setara dengan

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

Di mana 'sesi' mengacu pada strategi berikut yang digabungkan dengan pasporJS.

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

Khususnya baris 59-60:

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

Di mana itu pada dasarnya bertindak sebagai middleware dan mengubah nilai properti 'pengguna' di objek req agar berisi identitas pengguna yang tidak dialihkan. Agar ini berfungsi dengan benar, Anda harus menyertakan serializeUserdan deserializeUserberfungsi di kode kustom Anda.

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

Ini akan menemukan pengguna yang benar dari database dan meneruskannya sebagai variabel closure ke dalam callback done(err,user);sehingga kode di atas passport.session()dapat menggantikan nilai 'user' di objek req dan meneruskannya ke middleware berikutnya dalam tumpukan.

lindsaymacvean.dll
sumber
hei, bagaimana saya bisa menyimpan detail pengguna hanya dalam sesi saya tidak ingin menyimpannya di database secara langsung
Newbiee
1
"di header permintaan"? tidak hanya di objek permintaan
caub
Saya perhatikan bahwa jika strategi sesi dapat memulihkan autentikasi dan menonaktifkan pengguna. Namun meski begitu otentikasi masih berpindah ke strategi selanjutnya, yaitu facebook auth dalam skenario saya. Saya ingin tahu apa gunanya strategi sesi jika masih terus menjalankan strategi berikut bahkan ketika sesi dapat memulihkan pengguna.
nishant
15

Dari dokumentasi

Dalam aplikasi Connect atau berbasis Express, middleware passport.initialize () diperlukan untuk menginisialisasi Passport. Jika aplikasi Anda menggunakan sesi login persisten, middleware passport.session () juga harus digunakan.

dan

Sesi

Dalam aplikasi web biasa, kredensial yang digunakan untuk mengautentikasi pengguna hanya akan dikirim selama permintaan login. Jika otentikasi berhasil, sesi akan dibuat dan dipertahankan melalui cookie yang ditetapkan di browser pengguna.

Setiap permintaan berikutnya tidak akan berisi kredensial, melainkan cookie unik yang mengidentifikasi sesi tersebut. Untuk mendukung sesi login, Passport akan membuat serial dan deserialisasi instance pengguna ke dan dari sesi tersebut.

dan

Perhatikan bahwa mengaktifkan dukungan sesi sepenuhnya opsional, meskipun disarankan untuk sebagian besar aplikasi. Jika diaktifkan, pastikan untuk menggunakan express.session () sebelum passport.session () untuk memastikan bahwa sesi login dipulihkan dalam urutan yang benar.

Josh C.
sumber
1
Terima kasih atas balasan cepat Anda, tetapi itu tidak menjawab pertanyaan saya. Juga, perhatikan bahwa jika Anda memiliki aplikasi ekspres dan menggunakan express.session (), pada klien mana pun yang terhubung ke server ekspres Anda (apakah dia diautentikasi atau tidak), dia akan diberikan sesi melalui cookie. Itu tidak tergantung pada apakah dia berada di halaman yang dilindungi login aplikasi Anda atau tidak. Saya masih ingin mengetahui perbedaan antara kedua middleware.
Georges Krinker
1
@GeorgesKrinker itu adalah metode serializeUser () dan deserializeUser. Middleware ekspres akan mengembalikan info sesi, tapi itu tidak selalu terkait dengan bagaimana paspor mengelola info pengguna. Itu harus dilakukan setelah sesi direhidrasi dengan mengungkapkan.
Josh C.
Saya mendapat kesan bahwa metode serializeUser () dan deserializeUser berjalan di otentikasi () dalam rute.
Georges Krinker
@GeorgesKerr Saya rasa tidak. Ketika saya menggunakan paspor, saya hanya menelepon .authenticate saat login.
Josh C.
app.post('/login', passport.authenticate('local'), ...
Josh C.
11

Meskipun Anda akan menggunakan PassportJsuntuk memvalidasi pengguna sebagai bagian dari URL login Anda, Anda masih memerlukan beberapa mekanisme untuk menyimpan informasi pengguna ini dalam sesi dan mengambilnya dengan setiap permintaan berikutnya (yaitu membuat serial / deserialisasi pengguna).

Jadi pada dasarnya, Anda mengautentikasi pengguna dengan setiap permintaan, meskipun otentikasi ini tidak perlu mencari database atau oauth seperti dalam respons login. Jadi paspor akan memperlakukan otentikasi sesi juga sebagai strategi otentikasi lainnya.

Dan untuk menggunakan strategi ini - yang diberi nama session, cukup gunakan pintasan sederhana - app.use(passport.session()). Perhatikan juga bahwa strategi khusus ini ingin Anda mengimplementasikan fungsi serialisasi dan deserialisasi untuk alasan yang jelas.

uniwalker
sumber
11

Ini hanya mengotentikasi sesi (yang diisi oleh express.session()). Ini setara dengan:

passport.authenticate('session');

seperti dapat dilihat pada kode di sini:

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

Jared Hanson
sumber
6
Maksud kamu apa? Ini berjalan di setiap permintaan dan tidak selalu memiliki kredensial untuk diautentikasi. Maukah Anda memberi saya sedikit lebih banyak detail tentang alur kerja yang terjadi pada setiap permintaan?
Georges Krinker
6
Ya, dijalankan pada setiap permintaan. ID sesi yang dihasilkan oleh Express, adalah ID unik yang secara kasar setara dengan token otentikasi yang dikirimkan browser dengan setiap permintaan. Data yang disimpan dalam sesi ini digunakan untuk memulihkan status otentikasi pengguna.
Jared Hanson
Halo @JaredHanson Bisakah Anda melihat ini . Saya tidak dapat menemukan jawabannya di mana pun?
Saras Arya
@ JaredHanson Saya mencoba menggunakan passport.js untuk mengautentikasi dengan server otorisasi sumber terbuka yang banyak digunakan yang sesuai dengan OAuth2. Tapi saya mendapatkan kesalahan. Apakah Anda bersedia membantu menyelesaikan masalah? Ini tautannya: stackoverflow.com/questions/38176236/…
DollarCoffee
@JaredHanson: Apa yang saya amati adalah bahwa objek req ditambah dengan info passport.user setelah login melalui google-oauth, hilang ketika permintaan berikutnya untuk halaman baru dilakukan di situs. Apakah ini perilaku yang diharapkan? Lalu saya bingung bagaimana cara mendapatkan kembali info pengguna yang baru saja masuk?
pengguna1102171