2017-11-24 6 views
6

node_aclpassport-localで試してみます。コードを実行すると、admin-user'/admin'のルートを確保できず、/loginページにリダイレクトされます。ACL - パスポートと一緒にaclを実装する

私の最小実行可能な例の下に検索:

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: '[email protected]', 
    role: 'admin', 
}, 
{ 
    id: 2, 
    username: 'user', 
    password: 'user', 
    email: '[email protected]', 
    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 

任意の提案は、なぜ、/adminだけadmin userなるルートを呼び出すことはできませんか?

返信いただきありがとうございます。

+0

。いくつかのテストの後に、 'HttpError:リソースにアクセスするためのアクセス権が不十分です'というメッセージが表示されました。ユーザーとしてログインした '/ admin'に返信しました。 – Stamos

答えて

2

"runnable"コードを実行できませんでしたので、私はそれをチェックするために少し変更しました。 それで、いくつかのテストの後、それはうまく動作するようです。それもチェックできますか?私は `/ステータスに関するGETを行なったし、私はその後、私は/adminGETを行なったし、私は

を得た

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

を得た後

/login?username=user&password=userPOSTをしたPOSTMANを使用して

<!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> 

私はadminとしてログインしました。私が/adminを再度呼び出すと、admin

私はapp.post('/login')を変更しなければなりませんでした。私がしなかった場合、req.loginを実行した後、passport.serializeUserが呼び出されなかった場合、クッキーは正しくありませんでした。

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') 
}) 

すべてのコード:

あなたはユーザーでログインしたときに、あなたの `/ status`ルートリターンを何
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: '[email protected]', 
    role: 'admin', 
}, 
{ 
    id: 2, 
    username: 'user', 
    password: 'user', 
    email: '[email protected]', 
    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 
+0

Thxもう1つの質問ですが、なぜあなたは 'setTimout'関数を' accessControl'関数に追加しましたか? – mrquad

+0

さらに、なぜreq.logIn(user、(err)=> {// < - ユーザを next() )にログインさせると、あなたはすでにパスポート経由でログインしていませんか?私はあなたの返信に感謝します! – mrquad

+0

setTimeoutを無視して、ユーザーが正しいグループに属しているかどうかを確認したいと考えました。私はちょっと待っていたので、aclの仕組みを100%知っていません。 – Stamos