ACL – 与护照一起实施acl

我正在尝试使用passport-local的 node_acl 。 当我运行我的代码时,我无法确保admin-user '/admin'的路由,并且我被redirect到/login页面。

在下面查找我的最小可运行示例:

 require('dotenv').config() const express = require('express') // const fs = require('fs') const path = require('path') const logger = require('morgan') const bodyParser = require('body-parser') const cookieParser = require('cookie-parser') const session = require('express-session') const passport = require('passport') const LocalStrategy = require('passport-local').Strategy const ACL = require('acl') // load user.json file // const d = fs.readFileSync(path.join(__dirname, '/../data/user.json')) // const userObj = JSON.parse(d) const userObj = [{ id: 1, username: 'admin', password: 'admin', email: 'admin@admin.com', role: 'admin', }, { id: 2, username: 'user', password: 'user', email: 'user@user.com', role: 'user', }, ] const app = express() // view engine setup app.set('views', path.join(__dirname, 'views')) app.set('view engine', 'pug') app.use(logger(process.env.LOG_ENV)) app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: false, })) app.use(express.static(path.join(__dirname, '/../public'))) app.use(cookieParser()) app.use(session({ secret: 'super-mega-hyper-secret', resave: false, saveUninitialized: false, })) /** * Passport Local */ app.use(passport.initialize()) app.use(passport.session()) function authenticate() { passport.serializeUser((user, done) => { done(null, user.id) }) passport.deserializeUser(async(id, done) => { // const user = await serviceAuth.findById(id) const user = userObj.find(item => item.id === id) done(null, user) }) // Sign in with username and Password passport.use('local', new LocalStrategy({ usernameField: 'username', }, async(username, password, done) => { const user = userObj.find(item => item.username === username) done(null, user) })) } const isAuthenticated = (req, res, next) => { if (req.isAuthenticated()) { res.locals.user = req.session.user return next() } res.redirect('login') } authenticate() /** * Node ACL */ function accessControl() { const nodeAcl = new ACL(new ACL.memoryBackend()) nodeAcl.allow([{ roles: 'admin', allows: [{ resources: '/admin', permissions: '*', }], }, { roles: 'user', allows: [{ resources: '/dashboard', permissions: 'get', }], }, { roles: 'guest', allows: [], }]) // Inherit roles // Every user is allowed to do what guests do // Every admin is allowed to do what users do nodeAcl.addRoleParents('user', 'guest') nodeAcl.addRoleParents('admin', 'user') nodeAcl.addUserRoles(1, 'admin') nodeAcl.addUserRoles(2, 'user') nodeAcl.addUserRoles(0, 'guest') return nodeAcl } /* function checkPermission(resource, action) { const access = accessControl() return (req, res, next) => { const uid = req.session.user.id access.isAllowed(uid, resource, action, (err, result) => { if (result) { next() } else { const checkError = new Error('User does not have permission to perform this action on this resource') next(checkError) } }) } } */ const getCurrentUserId = (req) => { console.log(req) req.user && req.user.id.toString() || false } const access = accessControl() // Routes app.get('/login', (req, res) => { res.render('login') }) app.post('/login', (req, res, next) => { passport.authenticate('local', (err, user) => { if (err) return next(err) if (!user) { return res.status(401).json({ error: 'Email or password is incorrect.', }) } return res.render('dashboard') })(req, res, next) }) app.get('/dashboard', [isAuthenticated, access.middleware()], (req, res) => { res.render('dashboard') }) app.get('/admin', [isAuthenticated, access.middleware()], (req, res) => { res.render('admin') }) app.get('/status', (request, response) => { access.userRoles(getCurrentUserId(request), (error, roles) => { response.send(`User: ${JSON.stringify(request.user)} Roles: ${JSON.stringify(roles)}`) }) }) // Start Server const port = process.env.APP_PORT || 8080 const host = process.env.APP_URL || 'localhost' app.listen(port, host, () => { console.log(`Listening on ${host}:${port}`) }) module.exports = app 

任何build议,为什么路线, /admin不能被称为只有admin user

预先感谢您的回复!

我无法运行你的“可运行”代码,所以我改变了一下,以检查出来。 所以经过一些testing,似乎它工作得很好。 你也可以检查一下吗?

使用POSTMAN我在/login?username=user&password=user上做了POST

之后,我在`/ status'上做了一个GET ,然后我得到了

 User: {"id":2,"username":"user","password":"user","email":"user@user.com","role":"user"} Roles: [] 

然后我做了一个GET /admin ,我得到了

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>HttpError: Insufficient permissions to access resource <br> &nbsp; &nbsp;at C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\acl\lib\acl.js:705:14 <br> &nbsp; &nbsp;at tryCatcher (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\util.js:16:23) <br> &nbsp; &nbsp;at Promise.successAdapter [as _fulfillmentHandler0] (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\nodeify.js:23:30) <br> &nbsp; &nbsp;at Promise._settlePromise (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\promise.js:566:21) <br> &nbsp; &nbsp;at Promise._settlePromise0 (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\promise.js:614:10) <br> &nbsp; &nbsp;at Promise._settlePromises (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\promise.js:693:18) <br> &nbsp; &nbsp;at Async._drainQueue (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\async.js:133:16) <br> &nbsp; &nbsp;at Async._drainQueues (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\async.js:143:10) <br> &nbsp; &nbsp;at Immediate.Async.drainQueues (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\async.js:17:14) <br> &nbsp; &nbsp;at runCallback (timers.js:789:20) <br> &nbsp; &nbsp;at tryOnImmediate (timers.js:751:5) <br> &nbsp; &nbsp;at processImmediate [as _immediateCallback] (timers.js:722:5) </pre> </body> </html> 

然后我作为pipe理员login,当我再次打电话给/admin我得到了admin

我不得不改变app.post('/login') 。 如果我没有做req.login那么passport.serializeUser从来没有被调用,该cookie是不正确的,导致不好的会议。

 app.post('/login', (req, res, next) => { passport.authenticate('local', (err, user) => { if (err) return next(err) if (!user) { return res.status(401).json({ error: 'Email or password is incorrect.', }) } req.logIn(user, function (err) { // <-- Log user in next(); }); })(req, res, next) },function(req,res){ res.send('dashboard') }) 

所有代码:

 require('dotenv').config() const express = require('express') // const fs = require('fs') const path = require('path') const logger = require('morgan') const bodyParser = require('body-parser') const cookieParser = require('cookie-parser') const session = require('express-session') const passport = require('passport') const LocalStrategy = require('passport-local').Strategy const ACL = require('acl') // load user.json file // const d = fs.readFileSync(path.join(__dirname, '/../data/user.json')) // const userObj = JSON.parse(d) const userObj = [{ id: 1, username: 'admin', password: 'admin', email: 'admin@admin.com', role: 'admin', }, { id: 2, username: 'user', password: 'user', email: 'user@user.com', role: 'user', }, ] const app = express() // view engine setup app.set('views', path.join(__dirname, 'views')) app.set('view engine', 'pug') app.use(logger(process.env.LOG_ENV)) app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: false, })) app.use(express.static(path.join(__dirname, '/../public'))) app.use(cookieParser()) app.use(session({ secret: 'super-mega-hyper-secret', resave: false, saveUninitialized: false, })) function authenticate() { passport.serializeUser((user, done) => { done(null, user.id) }) passport.deserializeUser((id, done) => { // const user = await serviceAuth.findById(id) const user = userObj.find(item => item.id === id) done(null, user) }) // Sign in with username and Password passport.use('local', new LocalStrategy({ usernameField : 'username', passwordField : 'password' }, async(username, password, done) => { const user = userObj.find(item => item.username === username) done(null, user) })) } const isAuthenticated = (req, res, next) => { if (req.isAuthenticated()) { res.locals.user = req.session.user return next() } res.redirect('login') } authenticate() /** * Passport Local */ app.use(passport.initialize()) app.use(passport.session()) /** * Node ACL */ function accessControl() { const nodeAcl = new ACL(new ACL.memoryBackend()) nodeAcl.allow([{ roles: 'admin', allows: [{ resources: '/admin', permissions: '*', }], }, { roles: 'user', allows: [{ resources: '/dashboard', permissions: 'get', }], }, { roles: 'guest', allows: [], }]) // Inherit roles // Every user is allowed to do what guests do // Every admin is allowed to do what users do nodeAcl.addRoleParents('user', 'guest') nodeAcl.addRoleParents('admin', 'user') nodeAcl.addUserRoles(1, 'admin') nodeAcl.addUserRoles(2, 'user') nodeAcl.addUserRoles(0, 'guest') return nodeAcl } /* function checkPermission(resource, action) { const access = accessControl() return (req, res, next) => { const uid = req.session.user.id access.isAllowed(uid, resource, action, (err, result) => { if (result) { next() } else { const checkError = new Error('User does not have permission to perform this action on this resource') next(checkError) } }) } } */ const getCurrentUserId = (req) => { console.log(req) req.user && req.user.id.toString() || false } const access = accessControl() // Routes app.get('/login', (req, res) => { res.send('login') }) app.post('/login', (req, res, next) => { passport.authenticate('local', (err, user) => { if (err) return next(err) if (!user) { return res.status(401).json({ error: 'Email or password is incorrect.', }) } req.logIn(user, function (err) { // <-- Log user in next(); }); })(req, res, next) },function(req,res){ res.send('dashboard') }) app.get('/dashboard', [isAuthenticated, access.middleware()], (req, res) => { res.send('dashboard') }) app.get('/admin', [isAuthenticated, access.middleware()], (req, res) => { res.send('admin') }) app.get('/status', (request, response) => { access.userRoles(getCurrentUserId(request), (error, roles) => { response.send(`User: ${JSON.stringify(request.user)} Roles: ${JSON.stringify(roles)}`) }) }) // Start Server const port = process.env.APP_PORT || 3335 const host = process.env.APP_URL || 'localhost' app.listen(port, host, () => { console.log(`Listening on ${host}:${port}`) }) module.exports = app