5

我正在寻找一种更好的方法来在 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。

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'
              }
            }
        },
4

2 回答 2

4

您的问题似乎是每次状态更改都会导致 POST 请求,必须先处理该请求才能切换状态。我假设您这样做是为了处理会话到期,或者因为您没有要检查的身份验证 cookie。

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

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

于 2014-01-14T20:55:04.983 回答
0

ui-router 有一个解决选项,应该清除印章。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
   });
}
于 2013-09-04T15:15:46.803 回答