如何根据用户在mean.js应用程序中的角色显示/隐藏路径

时间:2015-06-28 14:35:06

标签: mean-stack meanjs

我正在构建一个基于mean.js样板的应用程序。在这个应用程序中,我需要能够根据登录用户是否具有特定角色来显示/隐藏某些路线/菜单项。我不确定在快速侧或角侧是否更好。例如,如果我有两个顶级菜单项:常见任务和管理任务,我只想向具有管理员角色的人显示管理任务。有人做过这样的事吗?

2 个答案:

答案 0 :(得分:0)

您必须同时使用服务器和客户端。

服务器将维护会话跟踪您的身份(ID和您的角色,无论是管理员,用户还是客户)一段时间,并将加密的令牌发送到客户端,客户端会将其存储在cookie中并将其发回每次发出请求时都要服务器。

  • 例如,您可以使用JWT等express-jwt中间件进行快速传输。
  • &安培; Passportjs用于验证身份。

此外,您还必须在服务器端管理您的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'
        }
      }
      });
  });

HTML:link& link

<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用户集合中有这样的角色之外,我不需要做任何其他事情