当前位置: 首页 > 面试题库 >

角度认证:避免针对不同的路由进行多次解析

古文康
2023-03-14
问题内容

我正在开发一个Angular应用程序。在此,我将在进入仪表板之前对用户进行身份验证。为了达到这个目的,我写了signIn functionas

登录功能

this.signIn = function(credentials) {
        console.info('AccountController[signIn] Called');

        AuthService
            .login(credentials)
            .then(function(authenticatedUser) {
                $scope.globals['currentUser'] = authenticatedUser;

                AuthService.setCurrentUser(authenticatedUser);

                $scope.globals['isAuthenticated'] = true;
                $location.path('/dashboard');

            }).catch(function(error) {
                console.warn('AccountController[signIn] :: ', error);
                Flash.Error(error);
                $scope.credentials.password = '';
            });
    };

我还想限制用户访问路由(如果尚未登录)。为此,我想到了this dirty code

路线

$stateProvider
        .state('signIn', {
            url: '/signIn',
            templateUrl: 'partials/signIn/signIn.html',
            data: {
                pageTitle: 'SignIn'
            },
            controller: 'AccountController',
            controllerAs: 'ac',
            resolve: {
                auth: ['$q', 'AuthService', function($q, AuthService) {
                    var userInfo = AuthService.isAuthenticated();
                    console.info('SignIn Route[isAuthenticated] :: ', userInfo);
                    if (!userInfo) {
                        return $q.when(userInfo);
                    } else {
                        return $q.reject({
                            isAuthenticated: true
                        });
                    }
                }]
            }
        })
        .state('dashboard', {
            url: '/dashboard',
            templateUrl: 'partials/dashboard.html',
            controller: 'DashboardController',
            access: {
                requiredLogin: true
            },
            resolve: {
                auth: ['$q', 'AuthService', function($q, AuthService) {
                    var authenticated = AuthService.isAuthenticated();
                    console.info('dashboard Route[isAuthenticated] :: ', authenticated);
                    if (authenticated) {
                        return $q.when(authenticated);
                    } else {
                        return $q.reject({
                            isAuthenticated: false
                        });
                    }
                }]
            }
        })
        .state('manageStudent', {
            url: '/manageStudent',
            templateUrl: 'partials/manageStudent.html',
            access: {
                requiredLogin: true
            },
            resolve: {
                auth: ['$q', 'AuthService', function($q, AuthService) {
                    var authenticated = AuthService.isAuthenticated();
                    if (authenticated) {
                        return $q.when(authenticated);
                    } else {
                        return $q.reject({
                            isAuthenticated: false
                        });
                    }
                }]
            }
        });


App.run(['$rootScope', 'settings', '$state', 'AuthService', '$location', function($rootScope, settings, $state, AuthService, $location) {
    $rootScope.$state = $state; // state to be accessed from view
    $rootScope.$settings = settings; // state to be accessed from view

    $rootScope.$on('$stateChangeStart', function(event, next,nextParams,prev,prevParams) {

        // If the user is logged in don't allow him to land on the Login Page


        if (next.access !== undefined) {
            if (next.access.requiredLogin && !AuthService.isAuthenticated()) {

                $location.path('/signIn');
            }
        }


    });


    $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {

        event.preventDefault();
        if (!error.isAuthenticated) {
            console.warn("I'm not Authenticated.Going to Sign-in");

            return $location.path('/signIn');
        } else {
            console.info("I'm Authenticated");
            $location.path('/dashboard');

        }
    });
}]);

我说上面的代码 DIRTY 的原因是,如果我要保护10条未授权用户使用的路由,则必须在所有路由中复制相同的resolve函数。

所以我的问题是,我应该怎么做才能摆脱多重解析功能并能够编写DRY代码?


问题答案:

由于auth应该在每次更改路线时都解决该问题,因此仅将其包装为单独的factory(这是一个单例并且仅运行一次)是不够的。为了解决这个限制,它应该是一个函数

app.factory('authResolver', function ($q, AuthService) {
  return function () {
    // ...
  };
});

在每条路线上运行

...
resolve: {
  auth: function (authResolver) {
    return authResolver();
  }
}

仍然不是那种干燥,但这是推荐的湿度水平。

可能从样板中resolve节省一个并节省几行代码的更激进的方法将类似于以下内容:

app.run(function ($rootScope, authResolver) {
  $rootScope.$on('$stateChangeStart', function (e, to) {
    if (to.doAuthPlease)
      to.resolve.auth = authResolver();
  });
});

...
doAuthPlease: true,
resolve: {}

提到的答案与ngRoute的明显区别是,在UIRouter中,您需要resolve定义对象才能动态地向状态添加新的解析器。可以像这样对待它,也可以照原样进行。



 类似资料:
  • 我在Grails应用程序中工作,希望在不同的文件中记录消息。我想在不同的文件中记录异常,正常和API日志。但是根据Log4j的一般角色,如果我们将记录器级别设置为'info',那么警告和错误消息也将开始登录到这个文件中,而我想在不同的文件中记录错误消息。因此,我的错误信息将被记录在错误文件和信息文件中。虽然我希望“信息”记录器只记录“信息”级别的消息,而不是“错误”级别的消息。而“错误”记录器只记

  • 问题内容: 我的网站流量很高,并且使用hibernate模式。我还使用ehcache缓存生成页面所需的一些实体和查询。 问题是“并行高速缓存未命中”,长原因是当应用程序启动且高速缓存区域变冷时,每个高速缓存区域将由不同线程填充多次(而不是仅一次),因为该站点受到许多用户的攻击与此同时。另外,由于相同的原因,当某些缓存区域无效时,它会被多次填充。如何避免这种情况? 我通过向hibernate.cac

  • 问题内容: 角度ui路由器的示例演示在起始页面具有以下链接: “ ui-router”的完整网址为或 “关于”的完整网址为或 当我使用durandalJS时,存在一个限制,即默认URL只是“ /”,不能有“ / ui-router”。 Angular ui路由器插件有相同的限制吗? 问题答案: 请参阅此处,默认路由有一个“其他”选项。

  • 我有一个使用Laravel 4和AngularJS构建的应用程序。除了注销之外,一切都很好。如果我直接访问路由(/user/logout),用户将成功注销并重定向回 /login页面。但是,当我尝试链接到视图中的laravel注销路由时,它不起作用。我认为角是阻塞。我试着玩了一些东西,但总是,网址在地址栏中出现一瞬间,什么也没发生。 从应用程序/视图/相册/index.blade.php publ

  • 我试图找出是否有一个更优化的方法在两个兄弟孩子路由之间共享同一个解析器。下面是一个路由与解析器相关的示例。 现在,我正在为每个子路由重复解析器调用,我认为这不是最优的。有人知道有没有更好的方法来共享来自共享同级子解析器的数据吗?我考虑将来自重复解析器的数据设置为共享服务,然后另一个子同级路由将访问来自服务的数据(而不是在解析器中进行另一个api调用)。还有其他更好的解决方案吗?

  • 如何在Angular 2应用程序中路由而不更改URL?(这是因为该应用程序位于Django应用程序页面上的几个选项卡之一下,其中适合保持URL不变。 目前我在里面有这样的东西 在<code>HomeComponent</code>中,用户页面的导航使用以下内容: 当我在Angular 2应用程序中导航时,可以保持网址不变吗?所以当用户在页面< code>user/123时,url将保持< code