【发布时间】:2016-03-31 19:40:22
【问题描述】:
我是 Express 4 的新手,我想知道如何实现这个东西:我正在使用 jwt 来验证我的 API 的使用者,为此我有一个漂亮的检查 jwt 令牌有效性的简单中间件:
var requireValidToken = function(req, res, next) {
var token = req.body.token || req.query.token || req.headers['x-access-token'];
if (token) {
try {
var decoded = jwt.verify(token, req.app.get('superSecret'));
} catch(err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
}
req.user = decoded.user;
next();
} else {
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
};
这工作得很好,但现在,我想扩展它以便能够检查用户的角色:
router.get('/anAdminRoute', requireRole('ROLE_ADMIN'), function (req, res, next) {
// some code...
});
所以我为此添加了一个中间件:
var requireRole = function(role) {
return function(req, res, next){
// Dummy tests...
if(req.user.role == roles.admin || req.user.role == role){
next();
} else {
return res.status(403)({
success: false,
message: "Token valid, but you don't have the right permission to access this resource :)"
});
}
}
}
但是由于这个 requireRole() 函数显然会检查一个有效的 jwt 令牌,我想知道如何在这个函数中调用我的 requireValidToken 中间件,因此不必为我想要保护的每条路由显式调用它。
一个简单的解决方案是不使用 requireValidToken 作为中间件,但我仍然希望能够使用它来保护某些路由
编辑:解决方案
链式中间件就是这么简单:
var middleware2 = function(param) {
return function(req, res, next){
middleware1(req, res, function(){
// middleware2 code
});
}
}
如果有人感兴趣,我验证用户角色的最终工作解决方案:
var jwt = require('jsonwebtoken'),
roles = require('../models/user').roles;
// authentication middleware
// check if the given jwt token is valid
var requireValidToken = function(req, res, next) {
var token = req.body.token || req.query.token || req.headers['x-access-token'];
if (token) {
try {
var decoded = jwt.verify(token, req.app.get('superSecret'));
} catch(err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
}
req.user = decoded.user;
next();
} else {
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
};
var requireRole = function(role) {
return function(req, res, next){
requireValidToken(req, res, function(){
if(req.user.role == roles.admin || req.user.role == role){
next();
} else {
return res.status(403).send({
success: false,
message: "Token valid, but you don't have the right permission to access this resource :)"
});
}
});
}
}
module.exports = {
requireValidToken: requireValidToken,
requireRole: requireRole
}
【问题讨论】:
-
晚了一点,但想指出,总的来说,即使令牌被加密——依赖客户端数据来确定特权级别,也是一个巨大的安全禁忌。理想情况下,令牌应该只验证用户的身份,并且应该从您控制的服务器端数据中提取权限和角色。如果您由于某种不明原因确实无法在服务器端存储用户权限/角色数据,我只会考虑此选项。