如何 show/hide 根据用户在 mean.js 应用程序中的角色进行路由

How to show/hide routes based on the user's role in a mean.js application

我正在构建一个基于 mean.js 样板的应用程序。在此应用中,我需要能够根据登录用户是否具有特定角色 show/hide 某些 routes/menu 项目。我不确定这是在快递方面还是 angular 方面做得更好。例如,如果我有两个顶级菜单项:普通任务和管理任务,我只想向具有管理员角色的人显示管理任务。有人做过这样的事吗?

您必须同时使用服务器和客户端来做到这一点。

服务器将在设定的时间内保持会话跟踪您的身份(ID 和您的角色,无论是管理员、用户还是访客),并向客户端发送加密令牌,客户端会将其存储在 cookie 中并发送每次发出请求时它都会返回服务器。

  • 例如,您可以使用 JWT 等 express-jwt 中间件作为 express。
  • & Passportjs 用于身份验证。

您还必须在服务器端照顾您的 API 路由。我已经从 DaftMonk/generator-angular-fullstack's 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);
        }
      }
    };

授权工厂: (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');
      }
    };
  });

用户工厂: (link) 当调用 get 时,服务器将 return 用户的详细信息(名称、角色、其他详细信息)。 (/api/users/me)

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)
});

事实证明这非常简单:只需在 .client.config 文件的 Menus.addMenuItem 行中添加一个明确的 ['myRole'] 元素。那里有许多位置参数,所以,一旦我真的费心阅读 mean.js 文档,它就在那里被明确指定。在 Menus.addMenuItem 中,我们可以完全控制命名、职位、允许的角色等......除了确保我的用户在 mongodb 用户合集