2014-10-16 16 views
8

Tôi đang sử dụng passport.js và tôi muốn flash một thông báo nếu các trường trong biểu mẫu của tôi trống. Nhưng tôi không biết làm thế nào để làm điều đó kể từ khi hộ chiếu không kích hoạt các cuộc gọi lại chiến lược nếu những người đang mất tích. Tôi thực sự muốn trường hợp sử dụng này rõ ràng hơn và tôi không muốn sửa đổi hộ chiếu. Tôi cảm thấy như có một cách để làm như vậy nhưng tôi không biết ở đâu! Tôi đã cố gắng sử dụng gọi lại của các tuyến đường (app.post) nhưng nó dường như không hoạt động theo cách tôi đã cố gắng.Xác thực Node.js với Hộ chiếu: Cách flash một tin nhắn nếu một trường bị thiếu?

Dưới đây là chức năng xác thực nguyên mẫu:

Strategy.prototype.authenticate = function(req, options) { 
    options = options || {}; 
    var username = lookup(req.body, this._usernameField) || lookup(req.query, this._usernameField); 
    var password = lookup(req.body, this._passwordField) || lookup(req.query, this._passwordField); 
    // here is my problem 
    if (!username || !password) { 
    return this.fail({ message: options.badRequestMessage || 'Missing credentials' }, 400); 
    } 

    var self = this; 

    function verified(err, user, info) { 
    if (err) { return self.error(err); } 
    if (!user) { return self.fail(info); } 
    self.success(user, info); 
    } 

    try { 
    if (self._passReqToCallback) { 
     this._verify(req, username, password, verified); 
    } else { 
     this._verify(username, password, verified); 
    } 
    } catch (ex) { 
    return self.error(ex); 
    } 
}; 

Đây là chiến lược của tôi:

passport.use('local-login', new LocalStrategy({ 
     usernameField : 'email', 
     passwordField : 'password', 
     passReqToCallback : true 
    }, 
    function(req, email, password, done) { 
     // ... 
     console.log("Hello"); 
     User.findOne({ 'local.email' : email }, function(err, user) { 
      if (err) 
       return done(err); 

      // if no user is found, return the message 
      if (!user) 
       return done(null, false, req.flash('loginMessage', 'Pas d\'utilisateur avec ce login.')); // req.flash is the way to set flashdata using connect-flash 

      // if the user is found but the password is wrong 
      if (!user.validPassword(password)) 
       return done(null, false, req.flash('loginMessage', 'Oops! Mauvais password.')); // create the loginMessage and save it to session as flashdata 

      // all is well, return successful user 
      return done(null, user); 
     }); 

    })); 

Và cuối cùng con đường của tôi:

app.get('/login', function(req, res) { 

    // render the page and pass in any flash data if it exists 
    res.render('login', { title: "Connexion", message: req.flash('loginMessage') }); 
}); 

// process the login form 
    app.post('/login', passport.authenticate('local-login', { 
     successRedirect : '/profile', // redirect to the secure profile section 
     failureRedirect : '/login', // redirect back to the signup page if there is an error 
     failureFlash : true // allow flash messages 
    }, function(err, user, info) { 
     // Was trying this callback, does'nt work, post callback maybe ? 
     console.log("Hello"); 
    })); 
+0

đâu là ngọc bích hoặc mẫu của bạn? bạn nên kiểm tra 'message', và hiển thị nếu nó hiện diện – anvarik

+0

Chính xác: Có một thông báo flash đã có khi người dùng hoặc mật khẩu sai, nhưng không phải khi các trường trống. Và tôi không thể quản lý để làm điều đó kể từ khi gọi lại trong chiến lược không được gọi trong kịch bản này bằng hộ chiếu (xem nguyên mẫu xác thực). Tôi không muốn hack vào mã hộ chiếu, phải có một cách .. –

+0

trả lại this.fail ({message: options.badRequestMessage || 'Thiếu thông tin đăng nhập'}, 400); <- điều này được trả về thay vào đó, và tôi không biết làm thế nào tôi có thể nhận được điều đó, ví dụ như trong hàm gọi lại app.post của tôi. –

Trả lời

12

Bạn không nên gọi số req.flash trong xác minh gọi lại. Thay vào đó, bạn nên trả lại một tin nhắn as shown in the documentation. Hộ chiếu sẽ đặt tin nhắn được trả về tin nhắn flash khi failureFlash: true.

sửa đổi xác minh callback của bạn:

passport.use('local-login', new LocalStrategy({...}, 
    function(email, password, done) { 
     User.findOne({ 'local.email' : email }, function(err, user) { 
      if (err) 
       return done(err); 
      if (!user) 
       return done(null, false, {message: 'Pas d\'utilisateur avec ce login.'}); 
      if (!user.validPassword(password)) 
       return done(null, false, {message: 'Oops! Mauvais password.'}); 
      return done(null, user); 
     }); 

    })); 

Và tuyến:

app.get('/login', function(req, res) { 
    console.log(req.flash('error')); 
    res.send(); 
}); 

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

Edit:

Dưới đây là một ví dụ làm việc đầy đủ: https://gist.github.com/vesse/9e23ff1810089bed4426

+0

uuh. Điều đó không giải quyết được vấn đề của tôi (các trường trống op op và ý kiến ​​op), cảm ơn bạn đã trả lời một trong hai cách. flash không được xác định nếu tôi sửa đổi mã của tôi theo cách bạn đề xuất. –

+1

Sau đó, có cái gì đó khác là sai. Tôi đã thêm một liên kết vào một gist chứa một ví dụ làm việc đầy đủ. – vesse

+0

Gần đây, tôi đã gặp sự cố này. Tôi nhìn qua nắm đấm của bạn và nhận thấy một vài điều tôi bỏ lỡ và điều này hoạt động hoàn hảo. Cảm ơn đã giúp đỡ! @vesse – PourMeSomeCode

3

Bạn cần phải thiết lập badRequestMessage và thiết lập failureFlash: true.

Như thế này:

passport.authenticate('login', { 
    successRedirect : '/', 
    failureRedirect : '/login', 
    badRequestMessage : 'Missing username or password.', 
    failureFlash: true 
}) 
3

Đó là một câu hỏi cũ, nhưng tôi có khó khăn khi tìm một câu trả lời. Hy vọng rằng điều này sẽ giúp người khác.


Tôi nghĩ rằng the documentation là một chút không đầy đủ khi nói đến việc sử dụng connect-flash. Họ nói:

Lưu ý: Sử dụng thông báo flash yêu cầu hàm req.flash(). Express 2.x cung cấp chức năng này, tuy nhiên nó đã bị xóa khỏi Express 3.x. Sử dụng phần mềm trung gian kết nối flash được khuyến nghị cung cấp chức năng này khi sử dụng Express 3.x.

Tuy nhiên, không đề cập đến việc sử dụng req.flash trong gọi lại done(). Dựa trên số scotch.io tutorial, bạn thực sự phải gọi gọi req.flash() ngay trong cuộc gọi lại. Nó làm việc cho tôi.

// In your strategy 
... 
if (user) { 
    return done(null, false, req.flash('loginMessage','Pas d\'utilisateur avec ce login.')); 
... 

Bạn sẽ cần sử dụng passReqToCallback tất nhiên. Ngoài ra, hãy chắc chắn failureFlash được đặt thành true. OP đã làm những điều này một cách chính xác.

Bây giờ bạn có thể kiểm tra thông báo flash trong tuyến đường. Lưu ý rằng connect-flash sẽ gửi một mảng thông báo. Đó có thể là vấn đề của OP, nếu mẫu của anh ta đang mong đợi một chuỗi.

// In your routes 
app.get('/login', function(req, res) { 

    // Test flash messages in the console 
    console.log(req.flash('loginMessage')); // This returns an array 
    console.log(req.flash('loginMessage')[0]); // This returns a string 

    // render the page and pass in any flash data if it exists 
    res.render('login', { 
     title: "Connexion", 
     message: req.flash('loginMessage')[0] // Don't forget the index! 
    }); 

}); 

Nếu có cơ hội có nhiều thông điệp đăng nhập trên trang, hãy chuyển toàn bộ mảng req.flash('loginMessage') và lặp lại thông qua mẫu trong mẫu của bạn. Dưới đây là ví dụ sử dụng nunjucks.


Protip:

Nếu bạn có nhiều tuyến đường với những thông điệp flash, bạn luôn có thể đặt chúng vào res.locals trong một con đường trung gian. Điều này sẽ không ảnh hưởng đến những người dân địa phương khác, chẳng hạn như title. Đây là triển khai của tôi, sử dụng bootstrap alerts.

Trong chiến lược của tôi:

... 
if (!user){ 
    return done(null, false, req.flash('danger','No account exists for that email.')); 
} 
... 

Trong routes.js tôi:

// Set flash messages 
router.get('*', function(req,res,next){ 
    res.locals.successes = req.flash('success'); 
    res.locals.dangers = req.flash('danger'); 
    res.locals.warnings = req.flash('warning'); 
    next(); 
}); 

// Login route 
app.get('/login', function(req, res) { 
    res.render('login', { title: 'Login'}); 
}); 

Trong nunjucks mẫu cơ sở của tôi:

<!--Messages--> 
{% for danger in dangers %} 
    <div class='header alert alert-danger alert-dismissible'> 
     <strong><i class="fa fa-exclamation-circle"></i> ERROR:</strong> {{ danger | safe }} 
     <a href="#" class='close' data-dismiss="alert" aria-label="close"><i class='fa fa-times'></i></a> 
    </div> 
{% endfor %} 
{% for warning in warnings %} 
    <div class='header alert alert-warning alert-dismissible'> 
     <strong><i class="fa fa-check-circle"></i> Warning:</strong> {{ warning | safe }} 
     <a href="#" class='close' data-dismiss="alert" aria-label="close"><i class='fa fa-times'></i></a> 
    </div> 
{% endfor %} 
{% for success in successes %} 
    <div class='header alert alert-success alert-dismissible'> 
     <strong><i class="fa fa-check-circle"></i> Success!</strong> {{ success | safe }} 
     <a href="#" class='close' data-dismiss="alert" aria-label="close"><i class='fa fa-times'></i></a> 
    </div> 
{% endfor %} 
Các vấn đề liên quan