护照:验证整个应用程序,而不是某些请求

时间:2018-07-20 07:02:41

标签: node.js express authentication passport.js passport-local

我是Web开发和NodeJS的新手。我正在使用护照进行身份验证。这是一个小应用程序,因此我对每个路由请求进行检查,以检查用户是否已通过身份验证;但是我想这种技术对于大型应用程序是不可行的。 我想验证整个应用程序。我知道它与中间件有关,因为每个请求都通过中间件传递,但是我不知道在哪里。任何与中间件相关的解释将不胜感激。

这是我的代码

const express = require('express');
const app = express();
const path = require('path');
const mongo = require('mongodb').MongoClient;
const cookieParser = require('cookie-parser');
const expressHandlebars = require('express-handlebars');
const expressValidator = require('express-validator');
const session = require('express-session');
const passport = require('passport');
const localStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const User = require('./models/user');
const Admin = require('./models/admin');


app.engine('handlebars', expressHandlebars({defaultLayout:'layout'}));
app.set('view engine', 'handlebars');

const port = 8888;
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());

app.use(session({
    secret: 'secret',
    saveUninitialized: true,
    resave: true
}));

app.use(passport.initialize());
app.use(passport.session());

//express Validator
app.use(expressValidator({
    errorFormatter: function(param, msg, value) {
        var namespace = param.split('.'),
            root = namespace.shift(),
            formParam = root;
        while (namespace.length) {
            formParam += '[' + namespace.shift() + ']';
        }
        return {
            param: formParam,
            msg: msg,
            value: value
        };
    }
}));

app.use(express.static(__dirname));

mongoose.Promise = global.Promise;
const url = 'mongodb://localhost:27017/userDB';
mongoose.connect(url);

这是我的登录功能。

app.get("/login", function (req, res) {
    const loginPath = path.join(__dirname, '/login.html');
    res.sendFile(loginPath);
});

passport.use(new localStrategy({
        usernameField: 'adminUsername',
        passwordField: 'password',
        session: false
    },
    function (adminUsername, password, done) {
        Admin.getAdminByAdminUsername(adminUsername, function (err, admin) {
            if (err) throw err;
            console.log('getAdmin called');
            if (!admin) {
                console.log('Admin Not Found');
                return done(null, false);
            }

            Admin.comparePassword(password, admin.password, function (err, isMatch) {
                console.log('comparePassword called');
                if (err) throw err;
                if (isMatch) {
                    return done(null, admin);
                } else {
                    console.log('Wrong Password!');
                    return done(null, false);
                }
            });
        });
    }));

passport.serializeUser(function (admin, done) {
    done(null, admin.id);
});
passport.deserializeUser(function (id, done) {
    Admin.getAdminById(id, function (err, admin) {
        done(err, admin);
        console.log('findById called');
    });
});

app.post('/login', passport.authenticate('local', {
        failureRedirect: '/login'}), function(req, res){
        console.log('login called');
        res.redirect('/');
    });

function ensureAuthenticated(req, res, next){
    console.log(req.isAuthenticated());
    if (req.isAuthenticated()) {
        return next();
    } else {
        res.redirect('/login');
    }
}

以前,这是我对每个请求进行检查的方式。这是一个例子。

app.get("/update", ensureAuthenticated, function (req, res) {
    const updatePath = path.join(__dirname, '/update.html');
    res.sendFile(updatePath);
});

1 个答案:

答案 0 :(得分:0)

ensureAuthenticated是一种中间件,您也可以单独使用它,如下所示:

app.use(ensureAuthenticated);

Express会将请求按照声明的顺序传递给中间件和路由处理程序。这意味着,如果您在其他中间件和路由处理程序的前面添加以上行,则对于每个请求都将始终调用该行(但请在下面阅读为什么您实际上不希望如此)。这样,您不必将其显式添加到每个请求处理程序中。

不过,通常,您将“需要身份验证的请求”与不需要的请求分开。例如,对静态资源(客户端JS,CSS,HTML等)的请求通常不需要身份验证。这意味着您需要在之前 ensureAuthenticated声明静态处理程序:

app.use(express.static(__dirname));
app.use(ensureAuthenticated);

属于登录过程的请求也是如此:登录页面和登录请求处理程序,原因很简单,要求用户在访问登录页面之前必须先登录。< / p>

因此,中间件/路由处理程序的总体结构如下:

  • 通用中间件(正文解析器,cookie处理程序,护照中间件等)
  • app.use(express.static(...))
  • 登录路线
  • app.use(ensureAuthenticated)
  • “受保护的”路线