18

我正在尝试在我的应用程序中实现用户身份验证检查和访问检查系统,但是我一直遇到障碍。我想这次我的方法是正确的,但我还有最后一个障碍。

一点背景知识:我尝试将所有代码放入 $rootScope.on($startChangeStart) 并且它有效,可怕......但它有效。该路由始终被重定向,但由于后端的身份验证检查,它以每秒 1/2 的速度显示第一个请求页面,然后每次都显示重定向页面。因此,我尝试通过在 $startChangeStart 函数的开头调用 evt.preventDefault() 来“暂停”页面加载,该函数有效,但随后试图将用户放回原始路由会导致路由器中的无限循环。

因此,经过更多研究和阅读大量堆栈帖子后,我确定“解决:”是放置身份验证检查以确保页面在发生时不加载的正确位置,然后在需要时从 $ 重定向用户开始改变开始。(在我尝试将 $state 和 event 注入 resolve 函数时,它们总是未定义)这似乎是成功的组合。

我的问题:我已经解决了我的应用程序中的根状态:'main'

这是为了避免代码冗余,但是我无法确定如何从 $stateChangeStart 函数访问根状态的属性以及解析结果。toState 是子状态,而 fromState 是前一个状态或带有 '^' 路由的抽象状态...

我是否必须对每个子状态都下定决心才能使它起作用,或者有没有办法从此时访问根状态?

基本应用设置:

angular.module('App', ['ui.router', 'ui.bootstrap', 'ui.event', 'AngularGM', 'ngResource'])
.config(['$urlRouterProvider', '$stateProvider', function($urlRouterProvider, $stateProvider){
    $urlRouterProvider
        .when('/home', '/')
        .when('', '/')
        .when('/sign-up/joe', '/sign-up')
        .otherwise('/');

    $stateProvider
        .state('main', {
            url: '',
            abstract: true,
            templateUrl: 'views/main.html',
            controller: 'MainCtrl',
            resolve: {
                checkAccess: ['accountService', function(accountService) {
                    accountService.checkAuth(function(){
                        accountService.checkAccess(function (access){
                            return access;
                        });
                    });
                }]
            }
        })
        .state('main.home', {
            url: '',
            abstract: true,
            templateUrl: 'views/home.html',
            controller: 'HomeCtrl'
        })
        .state('main.home.index', {
            url: '/',
            templateUrl: 'views/home/index.html'
        });


.run(['$rootScope', '$state', '$stateParams', 'accountService', function ($rootScope, $state, $stateParams) {
    $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
        console.dir(toState);
        console.dir(toParams);
        console.dir(fromState);
        console.dir(fromParams);
        if (!toState.checkAccess.allowed) {
            event.preventDefault();
            $state.transitionTo(toState.checkAccess.newState);
        }
    });
}]);

这是 console.dir() 调用两个状态对象的输出:

Object
 name: "main.home.index"
 templateUrl: "views/home/index.html"
 url: "/"
 __proto__: Object

Object
 controller: "PlacesCtrl"
 name: "main.places.search"
 templateUrl: "views/places.html"
 url: "/places"
 __proto__: Object

更新

糟糕,忘了说 AngularJS 版本是 v1.2.0-rc.2

$state.current 控制台.dir()

Object
 abstract: true
 name: ""
 url: "^"
 views: null
 __proto__: Object
4

5 回答 5

8

$stateChangeStart是的,我相信您可以从该功能访问根状态。

使用纯 AngularJS 时,我通常使用current.$$route

例如,使用以下路线

.when('/home', {
  title:'Home',
  bodyClass: 'meetings',
  controler: 'HomeCtrl'
})

我可以像这样访问根状态

  $rootScope.$on('$routeChangeSuccess', function (event, current, previous) {

   if (current.$$route) {

     $rootScope.title      = current.$$route.title;

     $rootScope.bodyClass  = current.$$route.bodyClass;
   }

 });

使用ui-router它只是有点不同,因为它被称为$state.current. 您可以访问与您点击的任何路线相关的所有属性(例如:$state.current.url)

所以在你的代码上你可以有这样的东西

  .run(['$rootScope', '$state', '$stateParams', function ($rootScope, $state, $stateParams) {

      $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
          console.log($state.current.url);
      });
  }]);
于 2013-10-02T18:15:31.737 回答
1

你不需要使用resolve. 看看我的解决方案:

app.run ($rootScope, $state, Auth, ngDialog) ->
  $rootScope.$on '$stateChangeStart', (e, to) ->
    if to.authRequired and not Auth.isAuthenticated()
      e.preventDefault()
      Auth.currentUser().then(
        (user) ->
          $state.go(to)
        (failure) ->
          $rootScope.storedState = to
          $state.go('main')
          ngDialog.closeAll()
          ngDialog.open
            template: 'modals/login.html'
            controller: 'loginCtrl'
            className: 'ngdialog-theme-default'
      )

我使用angular_devisengDialog但它们是可选的,您可以使用自己的用户服务来实现它。

于 2014-06-01T20:23:59.983 回答
0

如果您在解析时使用默认的空对象初始化您的状态,您将能够在$stateChangeStart.

$stateProvider
  .state 'home',
    url: "/"
    resolve: {}

...

  $rootScope.$on '$stateChangeStart', (e, toState, toParams, fromState, fromParams) ->
    toState.resolve.x = ->
      $timeout ->
        alert "done"
      , 3000

https://github.com/angular-ui/ui-router/issues/1165

于 2014-08-29T01:12:30.533 回答
0

是否可以从您的内部进行重定向accountService?如果您检测到用户未通过您的 checkAuth 或 checkAccess 功能,您可以阻止回调执行并将用户重定向到您的错误(或登录)页面。

如果您想将某人重定向到登录页面以刷新他们的授权/身份验证然后返回到先前的状态,则需要考虑的其他事情是实现某种变量/状态队列。

于 2013-12-10T17:18:35.533 回答
0

这个答案很晚,但它可能很有用。

状态和$stateChangeStart事件的解析同时执行。当您尝试访问 中的已解析数据时$stateChangeStart,它将不可用,但在$stateChangeSuccess事件触发时将可用。

如果你使用$stateChangeStart,那么你需要checkAuth从两个地方做$stateChangeStart事件和主要解决。由于它们具有并行执行,因此至少有 2 个网络请求将发送到服务器以获取相同的数据。

而是使用$stateChangeSuccess. 使用这将确保您的解析得到解决,然后您可以检查访问权限。此外,不是访问解析的属性,而是使用角度服务访问解析的数据。

于 2017-04-18T05:45:08.343 回答