如何使用AngularJS ngView隐藏未经授权的用户模板?

12

我有一个基本的PHP应用程序,用户登录信息存储在HTTP会话中。该应用程序有一个主模板,比如index.html,使用ngView切换子视图,如下所示:

我有一个基本的 PHP 应用,将用户登录存储在 HTTP 会话中。这个应用有一个主要的模板,比如 index.html,在 ngView 中切换子视图,如下所示:

<body ng-controller='MainCtrl'>
    <div ng-view></div>
</body>

现在,这个主模板可以通过基本的PHP控件进行保护,但我有一些子模板(例如,用户列表、添加用户、编辑用户等)是纯HTML文件,根据我的路由设置从angular中包含。

虽然我能够检查http服务请求的身份验证,但一个用户仍然能够浏览到子模板的URL并访问它。我该如何防止这种情况发生?


您是想将子模板简单地隐藏起来,以防止非特权用户看到它们,还是想要让他们无法知道该模板的存在? - James deBoer
这两件事都是最好的目标。 - brazorf
2个回答

14

我会创建一个类似这样的服务:

app.factory('routeAuths', [ function() {
  // any path that starts with /template1 will be restricted
  var routeAuths = [{
      path : '/template1.*',
      access : 'restricted'
  }];
  return {
    get : function(path) {
      //you can expand the matching algorithm for wildcards etc.
      var routeAuth;
      for ( var i = 0; i < routeAuths.length; i += 1) {
        routeAuth = routeAuths[i];
        var routeAuthRegex = new RegExp(routeAuth.path);
        if (routeAuthRegex.test(path)) {
          if (routeAuth.access === 'restricted') {
            return {
              access : 'restricted',
              path : path
            };
          }
        }
      }
      // you can also make the default 'restricted' and check only for 'allowed'
      return {
        access : 'allowed',
        path : path
      };
    }
  };
} ]);

还有在主/根控制器中监听$locationChangeStart事件:

app.controller('AppController', ['$scope', '$route', '$routeParams', '$location', 'routeAuths',
  function(scope, route, routeParams, location, routeAuths) {
    scope.route = route;
    scope.routeParams = routeParams;
    scope.location = location;

    scope.routeAuth = {
    };

    scope.$on('$locationChangeStart', function(event, newVal, oldVal) {
      var routeAuth = routeAuths.get(location.path());
      if (routeAuth.access === 'restricted') {
        if (scope.routeAuth.allowed) {
          event.preventDefault();
        }
        else {
          //if the browser navigates with a direct url that is restricted
          //redirect to a default
          location.url('/main');
        }
        scope.routeAuth.restricted = routeAuth;
      }
      else {
        scope.routeAuth.allowed = routeAuth;
        scope.routeAuth.restricted = undefined;
      }
    });

}]);

示例:

参考资料:

更新:

为了完全防止html模板访问,最好也在服务器上进行处理。因为如果您从服务器的静态文件夹中提供html,则用户可以直接访问该文件,例如:root_url/templates/template1.html,从而规避angular检查器。


这似乎是一个不错的解决方案,但是如果用户导航到http://srv/sub-templates-dir/template1.html,他仍然能够加载模板。这个检查应该在服务器端实现吗? - brazorf
实现只是检查路径的相等性,但您可以实现一个更复杂的检查系统。我更新了我的答案。 - Liviu T.
@LiviuT. 我想问一下如何绕过路由授权,比如说用户已经成功认证,那么他应该能够查看template1。我该如何将路由访问权限从受限改为允许? - Wondering Coder
我建议登录功能在服务上设置一个标志,然后将该服务注入控制器,并在事件监听器中检查类似于(UserStatus.isLoggedIn || scope.routeAuth.allowed)的内容。 - Liviu T.

0
如果您想阻止他们访问该页面,请创建一个服务:http://docs.angularjs.org/guide/dev_guide.services.creating_services 此服务可以通过所有已注册路由参数的控制器进行依赖注入。
在服务中,您可以编写一个函数来检查用户是否已登录,然后使用http://docs.angularjs.org/api/ng.$location#path将其重定向(例如返回到登录页面)。在每个控制器中调用此函数,如下所示:
function myController(myServiceChecker){
    myServiceChecker.makeSureLoggedIn();
}

makeSureLoggedIn函数将检查当前url路径(使用$location.path)并且如果不被允许,将重定向至被允许的页面。

我很想知道是否有一种方法可以防止routeParams触发,但至少这样可以让您按照自己的意愿操作。

编辑:还请参见我的答案,可以防止他们甚至进入该页面:

AngularJS - 检测、暂停和取消路由变化


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接