tki*_*dle 10
我找到了解决方案.听到人们对此的看法会很棒.
我有一个权限配置对象,它定义了每个角色及其权限.
权限配置对象
roles.admin = {
id: "admin",
name: "Admin",
description: "",
resource : [
{
id : 'blog',
permissions: ['create', 'read', 'update', 'delete']
},
{
id : 'user',
permissions: ['create', 'read', 'update', 'delete']
},
{
id : 'journal',
permissions: ['create', 'read', 'update', 'delete']
},
]
};
roles.editor = {
id: "editor",
name: "Editor",
description: "",
resource : [
{
id : 'blog',
permissions: ['create', 'read', 'update', 'delete']
},
{
id : 'user',
permissions: ['read']
},
{
id : 'journal',
permissions: ['create', 'read', 'update']
},
]
};
Run Code Online (Sandbox Code Playgroud)
中间件功能
var roles = require('./config');
var permissions = (function () {
var getRoles = function (role) {
var rolesArr = [];
if (typeof role === 'object' && Array.isArray(role)) {
// Returns selected roles
for (var i = 0, len = role.length; i < len; i++) {
rolesArr.push(roles[role[i]]);
};
return rolesArr;
} else if (typeof role === 'string' || !role) {
// Returns all roles
if (!role) {
for (var role in roles) {
rolesArr.push(roles[role]);
};
}
// Returns single role
rolesArr.push(roles[role]);
return rolesArr;
}
},
check = function (action, resource, loginRequired) {
return function(req, res, next) {
var isAuth = req.isAuthenticated();
// If user is required to be logged in & isn't
if (loginRequired && !isAuth) {
return next(new Error("You must be logged in to view this area"));
}
if (isAuth || !loginRequired) {
var authRole = isAuth ? req.user.role : 'user',
role = get(authRole),
hasPermission = false;
(function () {
for (var i = 0, len = role[0].resource.length; i < len; i++){
if (role[0].resource[i].id === resource && role[0].resource[i].permissions.indexOf(action) !== -1) {
hasPermission = true;
return;
}
};
})();
if (hasPermission) {
next();
} else {
return next(new Error("You are trying to " + action + " a " + resource + " and do not have the correct permissions."));
}
}
}
}
return {
get : function (role) {
var roles = getRoles(role);
return roles;
},
check : function (action, resource, loginRequired) {
return check(action, resource, loginRequired);
}
}
})();
module.exports = permissions;
Run Code Online (Sandbox Code Playgroud)
然后我创建了一个中间件函数,当调用check方法时,它从req对象(req.user.role)获取用户角色.然后它查看传递给中间件的参数,并将它们与权限配置对象中的参数交叉引用.
与middlware路由
app.get('/journal', `**permissions.check('read', 'journal')**`, function (req, res) {
// do stuff
};
Run Code Online (Sandbox Code Playgroud)
这是我的实现。该代码可用于客户端和服务器。我将其用于我的快速/角度网站
在app / both / both.js中
var accessList = {
//note: same name as controller's function name
assignEditor: 'assignEditor'
,adminPage: 'adminPage'
,editorPage: 'editorPage'
,profilePage: 'profilePage'
,createArticle: 'createArticle'
,updateArticle: 'updateArticle'
,deleteArticle: 'deleteArticle'
,undeleteArticle: 'undeleteArticle'
,banArticle: 'banArticle'
,unbanArticle: 'unbanArticle'
,createComment: 'createComment'
,updateComment: 'updateComment'
,deleteComment: 'deleteComment'
,undeleteComment: 'undeleteComment'
,banComment: 'banComment'
,unbanComment: 'unbanComment'
,updateProfile: 'updateProfile'
}
exports.accessList = accessList
var resourceList = {
//Note: same name as req.resource name
profile: 'profile'
,article: 'article'
,comment: 'comment'
}
exports.resourceList = resourceList
var roleList = {
admin: 'admin'
,editor: 'editor'
,entityCreator: 'entityCreator'
,profileOwner: 'profileOwner' //creator or profile owner
,normal: 'normal' //normal user, signed in
,visitor: 'visitor' //not signed in, not used, open pages are uncontrolled
}
var permissionList = {}
permissionList[accessList.assignEditor] = [roleList.admin]
permissionList[accessList.adminPage] = [roleList.admin]
permissionList[accessList.editorPage] = [roleList.admin, roleList.editor]
permissionList[accessList.profilePage] = [roleList.admin, roleList.editor, roleList.normal]
permissionList[accessList.createArticle] = [roleList.admin, roleList.editor, roleList.normal]
permissionList[accessList.updateArticle] = [roleList.admin, roleList.editor, roleList.entityCreator]
permissionList[accessList.deleteArticle] = [roleList.admin, roleList.editor, roleList.entityCreator]
permissionList[accessList.undeleteArticle] = [roleList.admin, roleList.editor, roleList.entityCreator]
permissionList[accessList.banArticle] = [roleList.admin, roleList.editor]
permissionList[accessList.unbanArticle] = [roleList.admin, roleList.editor]
permissionList[accessList.createComment] = [roleList.admin, roleList.editor, roleList.normal]
permissionList[accessList.updateComment] = [roleList.admin, roleList.editor, roleList.entityCreator]
permissionList[accessList.deleteComment] = [roleList.admin, roleList.editor, roleList.entityCreator]
permissionList[accessList.undeleteComment] = [roleList.admin, roleList.editor, roleList.entityCreator]
permissionList[accessList.banComment] = [roleList.admin, roleList.editor]
permissionList[accessList.unbanComment] = [roleList.admin, roleList.editor]
permissionList[accessList.updateProfile] = [roleList.admin, roleList.profileOwner]
var getRoles = function(access, resource, isAuthenticated, entity, user) {
var roles = [roleList.visitor]
if (isAuthenticated) {
roles = [roleList.normal]
if (user.username === 'admin')
roles = [roleList.admin]
else if (user.type === 'editor')
roles = [roleList.editor]
if (resource) {
if (resource === resourceList.profile) {
//Note: on server _id is a object, client _id is string, which does not have equals method
if (entity && entity._id.toString() === user._id.toString())
roles.push(roleList.profileOwner)
}
else if (resource === resourceList.article) {
if (entity && entity.statusMeta.createdBy._id.toString() === user._id.toString())
roles.push(roleList.entityCreator)
}
else if (resource === resourceList.comment) {
if (entity && entity.statusMeta.createdBy._id.toString() === user._id.toString())
roles.push(roleList.entityCreator)
}
}
}
return roles
}
exports.havePermission = function(access, resource, isAuthenticated, entity, user) {
var roles = getRoles(access, resource, isAuthenticated, entity, user)
//Note: we can implement black list here as well, like IP Ban
if (!permissionList[access])
return true
for (var i = 0; i < roles.length; i++) {
var role = roles[i]
if (permissionList[access].indexOf(role) !== -1)
return true
}
return false
}
Run Code Online (Sandbox Code Playgroud)
然后在app / server / helper.js上(充当适配器)
var both = require(dir.both + '/both.js')
exports.accessList = both.accessList
exports.resourceList = both.resourceList
exports.havePermission = function(access, resource, req) {
return both.havePermission(access, resource, req.isAuthenticated(), req[resource], req.user)
}
//todo: use this function in other places
exports.getPermissionError = function(message) {
var err = new Error(message || 'you do not have the permission')
err.status = 403
return err
}
exports.getAuthenticationError = function(message) {
var err = new Error(message || 'please sign in')
err.status = 401
return err
}
exports.requiresPermission = function(access, resource) {
return function(req, res, next) {
if (exports.havePermission(access, resource, req))
return next()
else {
if (!req.isAuthenticated())
return next(exports.getAuthenticationError())
else
return next(exports.getPermissionError())
}
}
}
Run Code Online (Sandbox Code Playgroud)
在app / client / helper.js上,还充当适配器。
exports.accessList = both.accessList
exports.resourceList = both.resourceList
exports.havePermission = function(access, resource, userService, entity) {
//Note: In debugging, we can grant client helper all access, and test robustness of server
return both.havePermission(access, resource, userService.isAuthenticated(), entity, userService.user)
}
Run Code Online (Sandbox Code Playgroud)
是的,您可以通过参数访问它request。
app.use(function(req,res,next){
console.log(req.method);
});
Run Code Online (Sandbox Code Playgroud)
http://nodejs.org/api/http.html#http_message_method
编辑:
误读了你的问题。分配用户权限并根据权限允许访问数据库可能会更好。我不明白你所说的通过与数据库交互进行验证是什么意思。如果您已经允许他们与数据库交互,但他们没有适当的权限这样做,这不是一个安全问题吗?