花了些时间初步了解了nodejs 和express 的运作方式.这几天准备做一个小的项目,在考虑到权限问题的时候却被卡住了.
我的需求是这样的. 单纯的用户认证这个应该很简单,passport这些都能胜任… 但是我想做的是针对每个请求URL进行权限控制.比如针对普通用户,
普通用户可以访问/user/updateSelf ,不能访问/user/addUser,而作为管理员可以访问任何一个链接. 这是第一方面
另外一方面,因为express也支持 restful的请求, 类似/user/:userId, /user/:action/:data ,如果采用这样的写法, 那么后台实际定义的URL是上面写的这样, 而接收过来的请求
URL 可能是 /user/12 , /user/save/u3 , 针对这样的URL 我又该怎么进行权限的控制呢.
我打算将所有定义的URL都和数据中的角色表进行映射, 比如 admin 对应 [/user/:userId,/user/:action/:data] 而普通用户角色 user对应 [/user/:userId]
那么 对于这样的路由 app.get(’/user/:action/:data’,function(res,req,next){…}) user就不会有权限访问.
但是我又该如何在处理请求之前获取 这些实际的url 诸如 /user/1 对应的是 /user/:userId 这个Url呢?
java中有反射,并且像struts这样的框架提供了拦截器,在执行action之前可以反射获取待执行的action,然后在判断URL和角色有无权限. 在nodejs中有这样的办法吗?
有人有好的办法吗 或者 有没有其他的权限控制框架. 让我不用为每个路由去配置权限. 而只要通过aop的方式,在执行所有的路由方法之前 判断权限?
我说一种比较常见的做法.
// 写一个验证middleware
var auth = function(req, res, next) {
var routePath=req.route.path;
// ....
}
app.get('/user/:action/:data’, auth, function(req, res, next) {
//...
});
app.get('/user/:userId’, auth, function(req, res, next) {
//...
});
@William17 这个我之前考虑过. 因为这样的写法还是得为每个路由手动在路由的声明上配置一个auth
因为路由是支持写多个function的. 所以我想有没有这样一种可能
假设原先路由是这样定义的. app.get(’/user/:action/:data’, function(req, res, next) { //… }); app.get(’/user/:userId’, function(req, res, next) { //… });
那么有没有像java中反射那样的机制来获取我所定义路由中的分别对应的function或者function数组. 这样我只需要在初始化路由的时候.为每个路由都push一个或者多个新的权限认证函数进去,类似你的auth.
比如 获取路径对应路由定义的 function = app.getRoutefunctions() 返回类似{path:’/user/:userId’,functions:[…一系列function]} 最后我只要遍历这个对象 functions.push(auth),这只是举例. 实际不知道有没有办法完成这样的功能. 如果能达到这样 我就不需要为每个路由都配置auth了
https://cnodejs.org/topic/551802d3687c387d2f5b2906#56069ca9148959375f34ff37 这边文章中说的和我的想法基本一样. 博主也提到了一个框架 sails 以及其中的sails-permissions
express中有无类似的中间件呢?
直接代码说话~
router.post('/post', checkLogin);
function checkLogin(req, res, next) {
if (!req.session.user) {
req.flash('error', '未登录!');
res.redirect('/login');
}
next();
}
那你这相当于要java里struts2的filter,那种貌似在session中存储权限列表,express里就在路由前加个中间件了
app.use(function(req, res, next) {
//判断当前访问url是否在权限列表
});
aop不是通常用来管理事务么…
@HengCC 这个也是中间件的一种呀,代码量虽然增加啦,但这个是自己可控,类似1楼的方法,在需要的地方添加。你可以直接用app.use自己写一个中间件也同理,但是用app.use真的是对每一个路由都验证,有些地方并不需要
@HengCC Token认证: if ((req.url.in****dexOf(‘admin’) >= 0 && dbUser.role == ‘admin’) || (req.url.indexOf(‘admin’) < 0 && req.url.indexOf(’/api/v1/’) >= 0)) { next(); // To move to next middleware } else {
http://thejackalofjavascript.com/architecting-a-restful-node-js-app/
以下代码片段应该是你要的效果: var myApp = angular.module(‘ngclient’, [‘ngRoute’]);
myApp.config(function($routeProvider, $httpProvider) {
$httpProvider.interceptors.push(‘TokenInterceptor’);
$routeProvider .when(’/login’, { templateUrl: ‘partials/login.html’, controller: ‘LoginCtrl’, access: { requiredLogin: false } }).when(’/’, { templateUrl: ‘partials/home.html’, controller: ‘HomeCtrl’, access: { requiredLogin: true } })