【问题标题】:Angularjs routing choppy when using authentication使用身份验证时Angularjs路由不稳定
【发布时间】:2013-09-08 04:05:33
【问题描述】:

我正在寻找一种更好的方法来在 angularjs 中进行路由状态之间的转换。目前,我一直在关注几个不同的教程,以使用服务器端的身份验证来配置带有后端 api 服务器的 angular。

http://frederiknakstad.com/authentication-in-single-page-applications-with-angular-js/ https://vickev.com/#!/article/authentication-in-single-page-applications-node-js-passportjs-angularjs

这两者都描述了在服务器端而不是在客户端进行身份验证的类似解决方案。我有一个角度身份验证服务,它使用一种方法发布到 api 服务器,检查用户是否使用 api 密钥登录。

isLoggedIn: function( event, toState ) {
        var user_api = {};

        if( "user" in $rootScope ) {
            user_api = { "api": $rootScope.user.api };
        } 

        $http.post('http://bac-api/authenticated/', user_api)
            .success( function( user ) {
                if( toState.url === '/login' && user.authenticated === true) {
                    $state.transitionTo('dashboard');
                }
            })
            .error( function( user ) {
                if( user.authenticated === false ) {
                    event.preventDefault();
                    $state.transitionTo('login');
                }
            });
    },

如果 api 密钥不存在,当然用户没有登录,服务器将发送 {"autheticated": false} 401 响应。如果用户有一个 api 密钥,它会使用该 api 密钥在服务器上检查它是否有效(已登录)或无效(未登录)。

为了捕获路由并检查用户是否经过身份验证,我使用“stateChangeStart”

$rootScope.$on("$stateChangeStart", function ( event, toState, toParams, fromState, fromParams ) {

    Auth.isLoggedIn( event, toState );

});  

这样做的第一个问题是在初始页面加载时不会触发状态更改,并导致使用 routeProvider 转换到登录页面。然后在整个应用程序中,如果请求的路由不在配置的路由中,它将转换到登录页面但不会触发 stateChangeStart。所以用户可以登录并坐在登录页面。我宁愿它作为我配置的路线转移到仪表板。

在大多数情况下,这种设置在理论上似乎可以正常工作,但路线很不稳定。因此,在检查用户是否登录之间会发生什么,路由将开始更改并开始显示页面,但是当应用程序意识到用户未登录时,它将切换到登录页面。我想解决这种波动。而不是瞥见其他页面能够正确传输。

我正在使用 ui-router 和应用程序中的所有状态。然后使用 Route Provider 仅在没有请求路由的路由时执行 $routeProvider.otherwise('login') 。

  1. 我想知道如何在应用程序检查用户是否经过身份验证时,在路由转换期间停止显示部分新页面(断断续续)。无论是在我不知道的不同事件中还是其他原因。

  2. 也是一种更好的方法,使用 routeProvider.otherwise() 来触发状态变化并检查用户是否已登录。如果已登录,则转移到仪表板,如果未登录,则在登录页面上停留,直到完成登录。

对不起,如果这太混乱了。我是 angularjs 的新手,并且一直在阅读我能找到的关于路由、状态和身份验证的所有内容。这是我学习如何在服务器端使用 Angular 管理身份验证的一个新概念。

-- 编辑

在接受 MBielski 的建议后,我已在各州实施解决方案以使用 Auth.isLoggedIn() 服务。但这仍然没有消除切换路线的波动,我什至担心一旦这不在本地开发中,等待 api 响应时波动会变得更糟。这是我的父仪表板状态的解析代码。

'dashboard-shell': {
            name: 'dashboard-shell',
            resolve: {
                Auth: function( Auth ) {
                    return Auth.isLoggedIn();
                }
            },
            views: {
              "dashboard-shell": {
                controller: 'DashboardController',
                templateUrl: 'app/modules/template-manager/partials/dashboard.tpl.html'
              }
            }
        },

【问题讨论】:

    标签: javascript authentication angularjs angular-ui-router


    【解决方案1】:

    您的问题似乎是每次状态更改都会导致一个 POST 请求,必须在您可以切换状态之前对其进行处理。我假设您这样做是为了处理会话到期,或者因为您没有要检查的身份验证 cookie。

    您基本上实现了一种悲观 方法,以确保在执行任何其他 HTTP 回调之前对用户进行身份验证。

    另一种方法可能是使用angular-http-auth HTTP 拦截器。这个拦截器提供了一种乐观的方法来确保用户被认证:它只是将每个HTTP调用传递到后端,但是你给它一个特殊的回调;当后端返回 403 Unauthorized 时,此回调用于例如显示登录对话框,以便用户可以(重新)进行身份验证。之后,拦截器重放所有导致 403 的 HTTP 调用。

    【讨论】:

    • 我会看看这个,因为我认为您每次发布帖子所需的时间是正确的。
    【解决方案2】:

    ui-router 有一个 resolve 选项,应该可以清除这个问题。 https://github.com/angular-ui/ui-router/wiki。解析部分中包含的任何内容都将在其余路由更改发生和页面加载之前完全解析。

    isLoggedIn: function( event, toState ) {
        var user_api = {};
    
        if( "user" in $rootScope ) {
            user_api = { "api": $rootScope.user.api };
        } 
    
        return $http.post('http://bac-api/authenticated/', user_api);
    },
    
    resolve: {
       var logged = Auth.isLoggedIn();
       logged.then(function(data){
           //success
       }, function(data){
          //failure
       });
    }
    

    【讨论】:

    • 我看到了这个,但有点不清楚如何实现 Auth 服务和使用 isLoggedIn()。我试图在路由中输入一个密钥来解决,但一直让 Auth 服务的 Provider 未知。如果它们位于不同的模块中,有没有办法在解析中使用 Auth 服务?
    • 获取提供者未知错误意味着您没有将其注入某处。我的第一个猜测是它没有注入您的应用程序。查看您尝试解析的路由的每个部分,并确保列出了您的身份验证服务以进行依赖注入。这将包括控制器、应用程序以及您可能拥有的可以引用该服务的任何其他服务或工厂。
    • 我在找到一篇新文章后能够解决工作,但这并没有解决断断续续的问题。
    • 你能发一个小提琴或 plunk 让我看看实际发生了什么吗?
    • 让您的 isLoggedIn 函数从您的帖子中返回承诺并在解决部分中采取行动。请参阅我编辑的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 2021-04-28
    • 2012-10-11
    • 1970-01-01
    相关资源
    最近更新 更多