我正在构建一个基于mean.js样板的应用程序。在这个应用程序中,我需要能够根据登录用户是否具有特定角色来显示/隐藏某些路线/菜单项。我不确定在快速侧或角侧是否更好。例如,如果我有两个顶级菜单项:常见任务和管理任务,我只想向具有管理员角色的人显示管理任务。有人做过这样的事吗?
答案 0 :(得分:0)
您必须同时使用服务器和客户端。
服务器将维护会话跟踪您的身份(ID和您的角色,无论是管理员,用户还是客户)一段时间,并将加密的令牌发送到客户端,客户端会将其存储在cookie中并将其发回每次发出请求时都要服务器。
此外,您还必须在服务器端管理您的API路由。我复制了DaftMonk/generator-angular-fullstack' demo app的相关代码。你应该看看下面的代码。
负责在每个请求中向服务器发送令牌的代码:(link)
.factory('authInterceptor', function ($rootScope, $q, $cookieStore, $location) {
return {
// Add authorization token to headers
request: function (config) {
config.headers = config.headers || {};
if ($cookieStore.get('token')) {
config.headers.Authorization = 'Bearer ' + $cookieStore.get('token');
}
return config;
},
// Intercept 401s and redirect you to login
responseError: function(response) {
if(response.status === 401) {
$location.path('/login');
// remove any stale tokens
$cookieStore.remove('token');
return $q.reject(response);
}
else {
return $q.reject(response);
}
}
};
Auth Factory:(link) 在客户端处理身份验证。登录后将令牌存储到cookie中,从服务器获取用户详细信息。
angular.module('demoApp')
.factory('Auth', function Auth($location, $rootScope, $http, User, $cookieStore, $q) {
var currentUser = {};
if($cookieStore.get('token')) {
currentUser = User.get();
}
return {
/**
* Authenticate user and save token
*
* @param {Object} user - login info
* @param {Function} callback - optional
* @return {Promise}
*/
login: function(user, callback) {
var cb = callback || angular.noop;
var deferred = $q.defer();
$http.post('/auth/local', {
email: user.email,
password: user.password
}).
success(function(data) {
$cookieStore.put('token', data.token);
currentUser = User.get();
deferred.resolve(data);
return cb();
}).
error(function(err) {
this.logout();
deferred.reject(err);
return cb(err);
}.bind(this));
return deferred.promise;
},
/**
* Delete access token and user info
*
* @param {Function}
*/
logout: function() {
$cookieStore.remove('token');
currentUser = {};
},
/**
* Gets all available info on authenticated user
*
* @return {Object} user
*/
getCurrentUser: function() {
return currentUser;
},
/**
* Check if a user is logged in
*
* @return {Boolean}
*/
isLoggedIn: function() {
return currentUser.hasOwnProperty('role');
},
/**
* Waits for currentUser to resolve before checking if user is logged in
*/
isLoggedInAsync: function(cb) {
if(currentUser.hasOwnProperty('$promise')) {
currentUser.$promise.then(function() {
cb(true);
}).catch(function() {
cb(false);
});
} else if(currentUser.hasOwnProperty('role')) {
cb(true);
} else {
cb(false);
}
},
/**
* Check if a user is an admin
*
* @return {Boolean}
*/
isAdmin: function() {
return currentUser.role === 'admin';
},
/**
* Get auth token
*/
getToken: function() {
return $cookieStore.get('token');
}
};
});
用户Facotry:(link) 当调用get时,服务器将返回用户的详细信息(名称,角色,其他详细信息)。 (/ API /用户/箱)
angular.module('demoApp')
.factory('User', function ($resource) {
return $resource('/api/users/:id/:controller', {
id: '@_id'
},
{
get: {
method: 'GET',
params: {
id:'me'
}
}
});
});
<li ng-show="isLoggedIn()"><a href="/settings">Client Aera</a></li>
<li ng-show="isAdmin()"><a href="/admin">Admin Aera</a></li>
在服务器上验证:(link) 此代码段处理登录路由的POST请求(此处为/ api / auth / local)
router.post('/', function(req, res, next) {
passport.authenticate('local', function (err, user, info) {
var error = err || info;
if (error) return res.json(401, error);
if (!user) return res.json(404, {message: 'Something went wrong, please try again.'});
var token = auth.signToken(user._id, user.role);
res.json({token: token});
})(req, res, next)
});
答案 1 :(得分:0)
这简直令人尴尬:只需在.client.config文件的Menus.addMenuItem行中添加一个显式的['myRole']元素。那里有许多位置参数,所以,一旦我真的打扰阅读mean.js文档,就会在那里明确指出。在Menus.addMenuItem中,我们可以完全控制命名,位置,允许的角色等等...除了确保我的用户确实在mongodb用户集合中有这样的角色之外,我不需要做任何其他事情