重构 passport.js 验证码

refactoring passport.js authentication code

我们有一个这样的 passport.js 文件:

const axios = require('axios')
const uuid = require('uuid/v4')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const session = require('express-session')
const mongoStore = require('connect-mongo')(session)

module.exports = (app) => {
    const users = [
        {
            id: '2f24vvg',
            email: 'test@test.com',
            password: 'password'
        }
    ]

    const mongoSessionStore = new mongoStore({
        url: 'mongodb://localhost/test-app',
        ttl: 30 * 60 // 30 min
    })

    let sess = {
        genid: (req) => {
            console.log('Inside the session middleware')
            console.log(req.sessionID)
            return uuid()
        },
        store: mongoSessionStore,
        secret: 'keyboard cat', // password from environment
        resave: false,
        rolling: true,
        saveUninitialized: true,
        unset: 'destroy', // removes the session from the server when end() is called
        cookie: {
            HttpOnly: true,
            maxAge: 30 * 60 * 1000 // 30 minutes
        }
    }

    app.use(session(sess))

    passport.use(new LocalStrategy(
        { usernameField: 'email' },
        (email, password, done) => {
            axios.get(`http://localhost:5000/users?email=${email}`)
                .then(res => {
                    const user = res.data[0]
                    if (!user) {
                        return done(null, false, { message: 'Invalid credentials.\n' })
                    }
                    if (password != user.password) {
                        return done(null, false, { message: 'Invalid password.\n' })
                    }
                    return done(null, user)
                })
                .catch(error => done(error))
        }
    ))

    passport.serializeUser((user, done) => {
        console.log('Inside serializeUser callback. User id is saved to the session store')
        done(null, user.id)
    })
    passport.deserializeUser((id, done) => {
        axios.get(`http://localhost:5000/users/${id}`)
            .then(res => done(null, res.data))
            .catch(error => done(error, false))
    })

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

我们有多个包含相同功能的路由器文件isAuthorized:

function isAuthorized(req, res, next) {
    if (req.isAuthenticated()) {
        console.log('Is allowed')
        next()
    }
    else {
        console.log('Is not allowed')
        res.sendStatus(401)
        // res.redirect('/')
    }
}
// Example in use:
router.get('/secure', isAuthorized, (req, res) => {
    res.format({
        html: () => {
            res.render('secure')
        },

        json: () => {
            res.send({ message: 'you reached the secure endpoint' })
        }
    })
})

为了避免在每个 routes.js 文件中都包含函数 isAuthorized,我们试图将其移动到一个模块中。为此,我认为将它添加到 passport.js 的末尾就足够了,如下所示:

module.exports = function isAuthorized(req, res, next) {
    if (req.isAuthenticated()) {
        console.log('Is allowed')
        next()
    }
    else {
        console.log('Is not allowed')
        res.sendStatus(401)
        // res.redirect('/')
    }
}

然而,当我们尝试在 route.js 文件中使用它时,我们得到了错误:

TypeError: req.isAuthenticated is not a function

这个功能怎么能脱离路由还能用呢?感谢您的帮助。

这就是你的中间件函数应该是什么样子

 module.exports = (req, res, next) => {

        if (req.Authenticated()) {
            return next();

        } else {

            res.status(401);
        }
    }

这就是您在其他(即 server.js)文件中使用中间件的方式

    const theMiddleWare = "/middlewareDir";
    app.use("/routes",theMiddleWare(),"routeDir");
// before doing this you have to add the passport middleware