Hiểu hộ chiếu tuần tự hóa deserialize


337

Làm thế nào bạn sẽ giải thích quy trình làm việc của các phương thức tuần tự hóa và giải tuần tự hóa của Hộ chiếu cho một giáo dân.

  1. Trường hợp nào user.idđi sau passport.serializeUserđã được gọi?

  2. Chúng tôi đang gọi passport.deserializeUserngay sau khi nó phù hợp với quy trình làm việc?

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user.id); 
       // where is this user.id going? Are we supposed to access this anywhere?
    });
    
    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });
    

Tôi vẫn đang cố quấn đầu quanh nó. Tôi có một ứng dụng hoạt động hoàn chỉnh và không gặp phải bất kỳ lỗi nào.

Tôi chỉ muốn hiểu chính xác những gì đang xảy ra ở đây?

Bất kỳ trợ giúp được đánh giá cao.

Câu trả lời:


451
  1. Trường hợp nào user.idđi sau passport.serializeUserđã được gọi?

Id người dùng (bạn cung cấp làm đối số thứ hai của donehàm) được lưu trong phiên và sau đó được sử dụng để truy xuất toàn bộ đối tượng thông qua deserializeUserhàm.

serializeUserxác định dữ liệu nào của đối tượng người dùng sẽ được lưu trữ trong phiên. Kết quả của phương thức serializeUser được đính kèm vào phiên dưới dạng req.session.passport.user = {}. Ví dụ ở đây, nó sẽ là (vì chúng tôi cung cấp id người dùng làm khóa)req.session.passport.user = {id: 'xyz'}

  1. Chúng tôi đang gọi passport.deserializeUserngay sau khi nó phù hợp với quy trình làm việc?

Đối số đầu tiên deserializeUsertương ứng với khóa của đối tượng người dùng được cung cấp cho donehàm (xem 1.). Vì vậy, toàn bộ đối tượng của bạn được lấy với sự giúp đỡ của khóa đó. Khóa đó ở đây là id người dùng (khóa có thể là bất kỳ khóa nào của đối tượng người dùng, ví dụ như tên, email, v.v.). Trong deserializeUserkhóa đó được khớp với mảng trong bộ nhớ / cơ sở dữ liệu hoặc bất kỳ tài nguyên dữ liệu nào.

Đối tượng tìm nạp được gắn vào đối tượng yêu cầu như req.user

Dòng chảy trực quan

passport.serializeUser(function(user, done) {
    done(null, user.id);
});              
                  
                 
                 └─────────────────┬──→ saved to session
                                       req.session.passport.user = {id: '..'}
                                   
                                              
passport.deserializeUser(function(id, done) {
                   ┌───────────────┘
                   
                    
    User.findById(id, function(err, user) {
        done(err, user);
    });            └──────────────→ user object attaches to the request as req.user   
});

2
Vì vậy, được user.idlưu dưới dạng req.session.passport.userhoặc được userlưu trữ dưới dạngreq.session.passport.user
Anubhav

@AB Tôi đã viết mã để tìm người dùng từ id đã được truyền cho phương thức deserialize làm tham số đầu tiên. Nhưng trong mọi yêu cầu, nó đang truy xuất người dùng từ db. Điều này làm giảm hiệu năng cho db. Tôi nên viết gì khác để giải tuần tự hóa chức năng để kiểm tra xem nó có tồn tại trên phiên hay không?
uzay95

2
@AB Tôi không hiểu những gì bạn đề xuất với uzay95. Vì vậy, trong phiên của tôi, tôi chỉ có user._id. Nhưng trên mỗi yêu cầu, tôi phải sử dụng id đó để giải nén từ cơ sở dữ liệu aka findUserByID và điều đó sẽ đưa nó vào req.user. Làm thế nào để tôi tránh thực hiện cuộc gọi như vậy trên mỗi yêu cầu?
Zanko

10
@Zanko Bạn có thể đưa toàn bộ đối tượng người dùng vào dữ liệu phiên, nhưng đó thường không phải là ý kiến ​​hay vì nó có thể có các tác dụng phụ khác. Ví dụ: khi người dùng cập nhật tên người dùng của bạn, bạn cũng phải cập nhật dữ liệu phiên, nếu không, bạn sẽ nhận được vé vì "tính năng đổi tên bị hỏng". Đó là một ví dụ tương đối vô hại. Điều tương tự có thể xảy ra với các bit cho phép hoặc dữ liệu nhạy cảm bằng nhau (Rất tiếc ...). Về cơ bản các vấn đề tương tự bạn luôn gặp phải nếu bạn có dữ liệu trùng lặp. TL; DR - Đừng làm điều đó.
Max Truxa

1
Nếu tôi không nhầm, các req.session.passport.user = {id: '..'}phần của sơ đồ là hơi bị sai, và nên req.session.passport.user = 785352thay vào đó, nơi 785352user.id. Tôi gặp sự cố khi đăng nhập bảng điều khiển để chứng minh điều đó, nhưng có vẻ như nó có ý nghĩa. Khi bạn gọi done(null, user.id);, sẽ hợp lý hơn khi lấy đối số thứ hai - user.idtrong trường hợp này - và gán nó cho req.session.passport.user, thay vì gán nó cho req.session.passport.user.id. Bởi vì nếu bạn thay vào đó userthì sao? req.sesssion.passport.user.id = usersẽ không có ý nghĩa.
Adam Zerner

21

Đối với bất cứ ai sử dụng Koa và koa-hộ chiếu :

Biết rằng khóa cho người dùng được đặt trong phương thức serializeUser (thường là một id duy nhất cho người dùng đó) sẽ được lưu trữ trong:

this.session.passport.user

Khi bạn đặt trong done(null, user)deserializeUser, trong đó 'user' là một số đối tượng người dùng từ cơ sở dữ liệu của bạn:

this.req.user HOẶC LÀ this.passport.user

vì một số lý do, this.userbối cảnh Koa không bao giờ được đặt khi bạn gọi xong (null, người dùng) trong phương thức deserializeUser của bạn.

Vì vậy, bạn có thể viết phần mềm trung gian của riêng mình sau cuộc gọi đến app.use (Passport.session ()) để đặt nó vào this.user như vậy:

app.use(function * setUserInContext (next) {
  this.user = this.req.user
  yield next
})

Nếu bạn không rõ về cách serializeUser và deserializeUser hoạt động, hãy đánh tôi trên twitter. @yvanscher


Xin lỗi vì đã hoại tử ở đây, nhưng bây giờ tôi có một mối quan tâm sau khi đọc lời giải thích giải trừ. Tôi đã đăng câu hỏi về vấn đề này tại đây trên SO: stackoverflow.com/questions/54154047/NH
Peter Kellner

Siêu hữu ích, nhưng vẫn có một số vấn đề đọc người dùng từ các tuyến khác. Có ai có thể giúp tôi ngoài này không? stackoverflow.com/questions/60709882/ Mạnh
Harry Lincoln
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.