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

Passport: Authenticating the whole app instead of some requests

我是网络开发和 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);
});

ensureAuthenticated 是一个中间件,你也可以独立使用,像这样:

app.use(ensureAuthenticated);

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

不过,通常情况下,您会将 "requests that require authentication" 与不这样做的请求分开。例如,对静态资源(客户端 JS、CSS、HTML 等)的请求通常不需要身份验证。这意味着您需要在 before ensureAuthenticated:

之前声明静态处理程序
app.use(express.static(__dirname));
app.use(ensureAuthenticated);

登录过程中的请求也是如此:登录页面和登录请求处理程序,原因很简单,要求用户先登录才能访问登录页面没有意义.

因此您的 middleware/route 处理程序的整体结构如下所示:

  • 常用中间件(正文解析器、cookie 处理程序、护照中间件等)
  • app.use(express.static(...))
  • 登录路径
  • app.use(ensureAuthenticated)
  • "Protected" 路线