พาสปอร์ตเซสชัน () มิดเดิลแวร์ทำอะไร


125

ฉันกำลังสร้างระบบการตรวจสอบการใช้ Passport.js ใช้โหนดรับรองความถูกต้องง่ายต่อการติดตั้งและการกวดวิชาท้องถิ่น

ฉันสับสนเกี่ยวกับสิ่งที่passport.session()ทำ

หลังจากที่เล่นรอบกับตัวกลางที่แตกต่างกันฉันมาที่จะเข้าใจว่าexpress.session()คือสิ่งที่จะส่งรหัสเซสชันคุกกี้ให้กับลูกค้า แต่ฉันสับสนเกี่ยวกับสิ่งที่ทำและทำไมมันเป็นสิ่งจำเป็นที่นอกเหนือไปจากpassport.session()express.session()

นี่คือวิธีตั้งค่าแอปพลิเคชันของฉัน:

// Server.js กำหนดค่าแอปพลิเคชันและตั้งค่าเว็บเซิร์ฟเวอร์

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

คำตอบ:


139

passport.session() ทำหน้าที่เป็นมิดเดิลแวร์เพื่อแก้ไขอ็อบเจ็กต์ req และเปลี่ยนค่า 'ผู้ใช้' ที่ปัจจุบันเป็นรหัสเซสชัน (จากคุกกี้ไคลเอ็นต์) เป็นอ็อบเจ็กต์ผู้ใช้ที่ไม่ได้กำหนดค่ากลางที่แท้จริง

ในขณะที่คำตอบอื่น ๆ ให้ประเด็นที่ดีฉันคิดว่าสามารถให้รายละเอียดที่เฉพาะเจาะจงมากขึ้นได้

app.use(passport.session());

เทียบเท่ากับ

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

โดยที่ 'เซสชัน' หมายถึงกลยุทธ์ต่อไปนี้ที่มาพร้อมกับพาสปอร์ต JS

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

บรรทัดที่ 59-60 โดยเฉพาะ:

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

โดยที่มันทำหน้าที่เป็นมิดเดิลแวร์เป็นหลักและปรับเปลี่ยนค่าของคุณสมบัติ 'ผู้ใช้' ในออบเจ็กต์ req เพื่อให้มีข้อมูลประจำตัวของผู้ใช้ เพื่อให้สามารถทำงานได้อย่างถูกต้องคุณต้องรวมserializeUserและdeserializeUserฟังก์ชันในโค้ดที่กำหนดเองของคุณ

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

สิ่งนี้จะค้นหาผู้ใช้ที่ถูกต้องจากฐานข้อมูลและส่งต่อเป็นตัวแปรการปิดไปยังการเรียกกลับdone(err,user);ดังนั้นโค้ดด้านบนpassport.session()สามารถแทนที่ค่า 'ผู้ใช้' ในออบเจ็กต์ req และส่งต่อไปยังมิดเดิลแวร์ถัดไปในกอง


เฮ้ฉันจะเก็บรายละเอียดผู้ใช้ในเซสชันได้อย่างไรฉันไม่ต้องการเก็บไว้ในฐานข้อมูลแบบผิด ๆ
Newbiee

1
"ในส่วนหัวของคำขอ"? ไม่เพียง แต่ในวัตถุที่ร้องขอ
caub

ฉันสังเกตเห็นว่าหากกลยุทธ์เซสชันสามารถกู้คืนการตรวจสอบสิทธิ์และยกเลิกการกำหนดค่าเริ่มต้นให้กับผู้ใช้ แต่ถึงแม้ว่าการรับรองความถูกต้องจะยังคงย้ายไปสู่กลยุทธ์ถัดไปซึ่งก็คือการรับรองความถูกต้องของ Facebook ในสถานการณ์ของฉัน ฉันสงสัยว่าอะไรคือจุดสำคัญของกลยุทธ์เซสชันหากยังคงเรียกใช้กลยุทธ์ต่อไปนี้แม้ว่าเซสชันจะสามารถกู้คืนผู้ใช้ได้
nishant

15

จากเอกสารประกอบ

ในแอปพลิเคชัน Connect หรือ Express จำเป็นต้องใช้มิดเดิลแวร์ passport.initialize () เพื่อเริ่มต้น Passport หากแอปพลิเคชันของคุณใช้เซสชันการเข้าสู่ระบบแบบถาวรต้องใช้มิดเดิลแวร์ passport.session () ด้วย

และ

การประชุม

ในเว็บแอปพลิเคชันทั่วไปข้อมูลประจำตัวที่ใช้ในการรับรองความถูกต้องของผู้ใช้จะถูกส่งระหว่างคำขอเข้าสู่ระบบเท่านั้น หากการรับรองความถูกต้องสำเร็จเซสชันจะถูกสร้างและดูแลผ่านชุดคุกกี้ในเบราว์เซอร์ของผู้ใช้

แต่ละคำขอที่ตามมาจะไม่มีข้อมูลรับรอง แต่เป็นคุกกี้เฉพาะที่ระบุเซสชัน เพื่อรองรับเซสชันการเข้าสู่ระบบ Passport จะทำให้เป็นซีเรียลไลซ์และยกเลิกการเชื่อมต่ออินสแตนซ์ของผู้ใช้เข้าและออกจากเซสชัน

และ

โปรดทราบว่าการเปิดใช้งานการสนับสนุนเซสชันเป็นทางเลือกทั้งหมดแม้ว่าจะแนะนำสำหรับแอปพลิเคชันส่วนใหญ่ หากเปิดใช้งานโปรดใช้ express.session () ก่อนพาสปอร์ตเซสชัน () เพื่อให้แน่ใจว่าเซสชันการเข้าสู่ระบบถูกเรียกคืนตามลำดับที่ถูกต้อง


1
ขอบคุณสำหรับการตอบกลับอย่างรวดเร็ว แต่ไม่ได้ตอบคำถามของฉัน นอกจากนี้โปรดทราบว่าหากคุณมีแอปพลิเคชันด่วนและใช้ express.session () บนไคลเอนต์ใด ๆ ที่เชื่อมต่อกับเซิร์ฟเวอร์ด่วนของคุณ (ไม่ว่าเขาจะได้รับการตรวจสอบสิทธิ์หรือไม่ก็ตาม) เขาจะได้รับเซสชันผ่านคุกกี้ นั่นเป็นอิสระว่าเขาอยู่ในหน้าการป้องกันการเข้าสู่ระบบของแอพของคุณหรือไม่ ฉันยังคงต้องการทราบความแตกต่างระหว่างมิดเดิลแวร์ทั้งสอง
Georges Krinker

1
@GeorgesKrinker เป็นวิธี serializeUser () และ deserializeUser มิดเดิลแวร์ด่วนจะกู้คืนข้อมูลเซสชัน แต่ไม่จำเป็นต้องเกี่ยวข้องกับวิธีที่หนังสือเดินทางจัดการข้อมูลผู้ใช้ ที่ต้องทำหลังจากเซสชันคืนสภาพโดยด่วน
Josh C.

ฉันรู้สึกว่าเมธอด serializeUser () และ deserializeUser ทำงานบนการพิสูจน์ตัวตน () ภายในเส้นทาง
Georges Krinker

@GeorgesKrinker ฉันไม่คิดอย่างนั้น เมื่อฉันใช้หนังสือเดินทางฉันเรียกว่า. authenticate เมื่อเข้าสู่ระบบเท่านั้น
Josh C.

app.post('/login', passport.authenticate('local'), ...
Josh C.

11

แม้ว่าคุณจะใช้PassportJsเพื่อตรวจสอบความถูกต้องของผู้ใช้โดยเป็นส่วนหนึ่งของ URL การเข้าสู่ระบบของคุณ แต่คุณยังคงต้องใช้กลไกบางอย่างในการจัดเก็บข้อมูลผู้ใช้นี้ในเซสชันและเรียกดูพร้อมกับทุกคำขอที่ตามมา

ดังนั้นคุณกำลังพิสูจน์ตัวตนผู้ใช้ด้วยทุกคำขอแม้ว่าการตรวจสอบสิทธิ์นี้ไม่จำเป็นต้องค้นหาฐานข้อมูลหรือ oauth เหมือนในการตอบกลับการเข้าสู่ระบบ ดังนั้นหนังสือเดินทางจะถือว่าการรับรองความถูกต้องเซสชันเป็นอีกหนึ่งกลยุทธ์การตรวจสอบสิทธิ์

และการใช้กลยุทธ์นี้ - ซึ่งเป็นชื่อsessionเพียงใช้ทางลัดง่าย app.use(passport.session())- นอกจากนี้โปรดทราบว่ากลยุทธ์เฉพาะนี้ต้องการให้คุณใช้ฟังก์ชัน serialize และ deserialize ด้วยเหตุผลที่ชัดเจน


11

เพียงแค่ตรวจสอบสิทธิ์เซสชัน (ซึ่งเติมข้อมูลโดยexpress.session()) เทียบเท่ากับ:

passport.authenticate('session');

ดังที่เห็นในรหัสที่นี่:

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


6
คุณหมายถึงอะไร? มันทำงานตามทุกคำขอและไม่จำเป็นต้องมีข้อมูลรับรองในการตรวจสอบสิทธิ์ คุณช่วยให้รายละเอียดเพิ่มเติมเกี่ยวกับขั้นตอนการทำงานที่เกิดขึ้นในแต่ละคำขอได้ไหม
Georges Krinker

6
ใช่มันทำงานตามคำขอทุกครั้ง รหัสเซสชันที่สร้างโดย Express เป็น ID เฉพาะซึ่งเทียบเท่ากับโทเค็นการตรวจสอบความถูกต้องที่เบราว์เซอร์ส่งไปพร้อมกับทุกคำขอ ข้อมูลที่จัดเก็บในเซสชันนี้ใช้เพื่อกู้คืนสถานะการพิสูจน์ตัวตนของผู้ใช้
Jared Hanson

สวัสดี @JaredHanson คุณช่วยดูสิ่งนี้ได้ไหม ฉันไม่พบคำตอบที่ไหน?
Saras Arya

@JaredHanson ฉันพยายามใช้ passport.js เพื่อตรวจสอบสิทธิ์กับเซิร์ฟเวอร์การอนุญาตโอเพนซอร์สที่ใช้กันอย่างแพร่หลายซึ่งเป็นไปตาม OAuth2 แต่ฉันได้รับข้อผิดพลาด คุณยินดีที่จะช่วยแก้ไขปัญหาหรือไม่ นี่คือลิงค์: stackoverflow.com/questions/38176236/…
DollarCoffee

@ JaredHanson: สิ่งที่ฉันสังเกตคือวัตถุ req ที่เติมเต็มด้วยหนังสือเดินทางข้อมูลผู้ใช้หลังจากเข้าสู่ระบบผ่าน google-oauth จะหายไปเมื่อมีการร้องขอหน้าใหม่ในเว็บไซต์ครั้งต่อไป เป็นพฤติกรรมที่คาดหวังหรือไม่? ถ้าอย่างนั้นฉันสูญเสียวิธีการคืนข้อมูลผู้ใช้ที่ล็อกอินล่าสุดหรือไม่?
user1102171
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.