1

我正在尝试使用护照对网页上的用户进行身份验证。一切正常,除非身份验证失败并且护照将用户重定向到相同的路线,否则表单上的所有数据都会丢失。有没有办法持久化数据并将它们传递回表单。

我在 routes.js 中有以下内容

// =====================================
// SIGNUP ==============================
// =====================================
// show the signup form
app.get('/signup', function(req, res) {
    // render the page and pass in any flash data if it exists
    signup.isAuthenticated = req.isAuthenticated();
    signup.user = req.user;
    signup.message = req.flash('signupMessage');
    res.render('signup', signup);
});

// process the signup form
app.post('/signup', passport.authenticate('local-signup', {
    successRedirect : '/', // redirect to the secure section
    failureRedirect : '/signup', // redirect back to the signup page if there is an error
    failureFlash : true // allow flash messages
})); 

在我的 passport.js 上,我有以下内容:

// =========================================================================
// LOCAL SIGNUP ============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'

passport.use('local-signup', new LocalStrategy({
        // by default, local strategy uses username and password, we will override with email
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true // allows us to pass back the entire request to the callback
    },
    // this function is used when signing up
    function(req, email, password, done) {
        // TODO: get the user from data
        if(email == 'myemail@gmail.com') {
            // user email already exists    
            console.log('user already exists !');
            return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
        } 
        else {

            // if there is no user with that email
            // create the user
            var newUser = { username : 'myemail@gmail.com', name : 'Name Surname' };
            newUser.local.email    = email;
            newUser.local.password = newUser.generateHash(password);
            return done(null, newUser);
        }
    }));   

我的 server.js 有以下内容:

// server.js

// set up ======================================================================
// get all the tools we need
var express  = require('express');
var path     = require('path');
var app      = express();
var port     = process.env.PORT || 3000;  
// var mongoose = require('mongoose');
var passport = require('passport');
var flash    = require('connect-flash');

var morgan       = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser   = require('body-parser');
var session      = require('express-session');
var multer       = require('multer');

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

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

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

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// set up our express application
app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.json()); // get information from html forms
app.use(bodyParser.urlencoded({ extended: false }));  

// use multer to process multi-part requests and multer to save our files by default to /uploads/ directory
app.use(multer({ 
            dest : path.join(__dirname, '/uploads/'),
            limits : {
                fieldNameSize : 200,       // 200 bytes 
                files : 5,                 // 5 files
                fileSize : 5194304000000,  // 5 GB 
                fields : 50                // 50 fields on the form                 
            }
}))

app.use(cookieParser()); // read cookies (needed for auth)
app.use(express.static(path.join(__dirname, 'public')));

// required for passport
app.use(session({ 
    secret: 'mylongsecretpassphrase', 
    resave : true, 
    saveUninitialized : true 
})); // session secret

app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session

// routes ======================================================================
require('./app/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport

// show error page if the resource is not found
app.use('*', function(req, res) {
  res.render('page-error', { 
    title : 'myWeb - Page Error',
    description : 'my web page',
    keywords : 'keywords1, keywords2, keywords3'
  });
});

// launch ======================================================================
app.listen(port);
console.log('Node listens on port ' + port);

任何帮助将不胜感激 !

4

2 回答 2

2

如果您不想丢失表单数据,可以使用 AJAX 发送表单,并发送状态 401 Unauthorized 以防身份验证失败。Passport 默认发送 401,因此以下内容应该有效(未经测试,可能包含拼写错误):

app.post('/login', function(req, res, next) {
    passport.authenticate('local-signup',
      function(req, res) {
       // If this function gets called, authentication was successful. If not, your ajax call gets a 401 status and you can handle it in .fail()
        res.redirect('/');
      });
});

护照网站的一些解释:

默认情况下,如果身份验证失败,Passport 将响应 401 Unauthorized 状态,并且不会调用任何其他路由处理程序。如果身份验证成功,将调用下一个处理程序并将 req.user 属性设置为经过身份验证的用户。

于 2014-10-12T00:32:24.993 回答
2

而不是使用默认的回调,如

passport.authenticate('local-signup', {
    successRedirect : '/', // redirect to the secure section
    failureRedirect : '/signup', // redirect back to the signup page if there is an error
    failureFlash : true // allow flash messages
})

您可以使用自定义回调,并通过像这样的闪存消息传递您想要的任何输入变量

router.post('/signup', function(request, response, next) {
    passport.authenticate('local-signup', function(err, user, info) {
        if (err)
            return next(err);

        if (!user) {
            // Attach flash messages to keep user input
            request.flash('emailInput', request.body.email);
            request.flash('usernameInput', request.body.username);

            return response.redirect('/signup');
        }

        // Note that when using a custom callback, it becomes the application's responsibility 
        // to establish a session (by calling req.login()) and send a response.
        request.logIn(user, function(err) {
            if (err)
                return next(err);

            return response.redirect('/profile');
        });
    })(request, response, next);
});

然后,当重定向时,您可以像往常一样将 Flash 消息发送到您的视图模板

response.render('signup.ejs', { 
    signupMessage: request.flash('signupMessage'),
    emailInput: request.flash('emailInput'),
    usernameInput: request.flash('usernameInput')
});
于 2016-09-07T10:09:07.857 回答