node权限控制模块node_acl的应用

前言

  • 一个应用必不可少的部分:登录认证(jaredhanson/passport)、权限控制(OptimalBits/node_acl)
  • 由于node_acl中文资料较少,本文给出一个完整的简单示例,便于初学者理解和学习
  • 最后有动态的效果图给出,更直观的展示node_acl的使用效果

知识点

  • 示例中的路由并未采用如:app.put('/blogs/:id', function(req, res, next){//…}的restful风格架构
  • 使用mongoose连接数据库
  • 初始化所有角色的权限
  • 建立父级角色(父级角色拥有子级角色所有权限)
  • 为用户添加角色(添加后,用户拥有该角色的所有权限)
  • es6模板字符串
  • 创建数据库schema模型
  • 为schema添加静态方法
  • 使用session保持会话
  • 自定义node_acl的认证失败后的错误信息
  • 使用错误中间件

示例

Promise = require('bluebird')
var express = require('express')
var mongoose = require('mongoose')
var session = require('express-session')
var MongoStore = require('connect-mongo')(session)
var acl = require('acl')

var app = express()

/*
 * ------------------------------------------------
 * 数据库
 */
mongoose.Promise = Promise
mongoose.connect('127.0.0.1:30001/blog')// 连接你自己的数据库
.then(() => {// 这里要注意,一定要在连接数据库之后进行权限的操作,否则不生效
    roles()// 权限
    routes()// 路由
})

app.use(session({
    secret: 'sign',
    resave: true,
    saveUninitialized: true,
    store: new MongoStore({mongooseConnection: mongoose.connection}),
}))

/*
 * --------------------------------------------------
 * 权限
 */
function roles() {
    acl = new acl(new acl.mongodbBackend(mongoose.connection.db, 'acl_'))
    // 为guestuseradmin角色添加权限
    acl.allow([
        {
            roles: 'guest',
            allows: [
                {resources: '/article/get', permissions: '*'},
            ],
        },
        {
            roles: 'user',
            allows: [
                {resources: '/article/edit', permissions: '*'},
            ],
        },
        {
            roles: 'admin',
            allows: [
                {resources: '/article/del', permissions: '*'},
            ],
        }
    ])
    acl.addRoleParents('user', 'guest')// user角色拥有guest角色所有的权限
    acl.addRoleParents('admin', 'user')// admin角色拥有user角色所有的权限
}

/*
 * --------------------------------------------------
 * 路由
 */
function routes() {
    // 渲染主页面
    app.all('/', (req, res, next) => {
        var html = `
            
<input class="name" type="text" placeholder="输入用户名" value="${Date.now()}" autocomplete="off"> <button class="add">创建用户button> <p>guest角色可以访问/article/get,user角色可以访问/article/edit,admin角色可以访问/article/delp> <p>默认情况下,访问1、2、3都会被拒绝p> <p>创建用户后,会自动给新创建的用户添加guest和 user角色,所以允许访问1、2p> <p>点击4后,删除了用户的user角色,只能访问1了p> <p> <span>1.span> <a href="/article/get" target="_blank">访问/article/geta> p> <p> <span>2.span> <a href="/article/edit" target="_blank">访问/article/edita> p> <p> <span>3.span> <a href="/article/del" target="_blank">访问/article/dela> p> <p> <span>4.span> <a href="/user/del" target="_blank">删除用户的user角色a> p> div> <script> window.onload = function() { document.querySelector('.add').onclick = function() { window.open('/user/add?name='+ document.querySelector('.name').value) } } script> ` res.send(html) }) var User = schema()// 获取用户模型实例 // 添加角色 app.all('/user/add', (req, res, next) => { User.add(req.query) .then((user) => { var _id = user._id.toString()// 注意_id默认是object类型 req.session.userId = _id// 写入session,标识该用户 acl.addUserRoles(_id, ['guest', 'user'])// 为用户添加guest和user的角色(那么用户就拥有了guest和user的权限) res.send({message: '添加用户角色成功'}) }) .catch((e) => { res.send({message: e.message}) }) }) // 删除角色 app.all('/user/del', (req, res, next) => { acl.removeUserRoles(req.session.userId, 'user') res.send({message: '删除用户角色成功'}) }) // 访问article app.all('/article/get', authentication, (req, res, next) => { res.send({message: '/article/get'}) }) // 编辑article app.all('/article/edit', authentication, (req, res, next) => { res.send({message: '/article/edit'}) }) // 删除article app.all('/article/del', authentication, (req, res, next) => { res.send({message: '/article/del'}) }) app.use(errorhandler) } /* * -------------------------------------------------- * schema */ function schema() { var schema = new mongoose.Schema({ name: { type: String, }, }) schema.statics = { add: function(obj) { return this .create(obj) }, } return mongoose.model('User', schema); } /* * -------------------------------------------------- * 中间件 */ // 认证中间件 var authentication = (req, res, next) => { var userId =req.session.userId || '' if(userId) { acl.isAllowed(userId, req.path, '*') .then(allowed => { if(allowed) { next() }else { next('权限不足') } }) .catch((e) => { next(e.message) }) }else { next('请登录') } } // 错误中间件 var errorhandler = (e, req, res, next) => { res.send({message: e}) } /* * -------------------------------------------------- * 开启服务 */ app.listen(3001, () => { console.log('server...') })

解释


  • 打开http://127.0.0.1:3000/可以看到
    node权限控制模块node_acl的应用_第1张图片
  • 数据库结构
    node权限控制模块node_acl的应用_第2张图片
  • 创建用户前访问接口(此时是未登录状态,没有任何权限)
    node权限控制模块node_acl的应用_第3张图片
  • 创建用户后访问接口(新用户自动添加guest和user角色,可访问1、2)
    node权限控制模块node_acl的应用_第4张图片
  • 删除user角色后(只能访问1)
    node权限控制模块node_acl的应用_第5张图片

icompuiz/express-mongoose-acl
Running ‘node_acl’ with mongoose on ExpressJS
RBAC角色权限设计思路

你可能感兴趣的:(node)