在初始化角时的最佳做法/模式进行用户身份验证? [英] Best practice/pattern for user authentication at init time in Angular?

查看:133
本文介绍了在初始化角时的最佳做法/模式进行用户身份验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要建一个角度SPA登录功能。我所有的登录/注销功能被封装在一个名为AuthService(其中,反过来,包了几$资源)的服务。用户被认为是登录,如果他们的浏览器有一个有效的PHP会话cookie。

I'm building the login functionality for an Angular SPA. All of my login/logout functionality is encapsulated in a service named AuthService (which, in turn, wraps a few $resources). The user is considered to be "logged in" if their browser has a valid PHP session cookie.

我所拥有的一切工作,除了一件事:在确定的时间初始化用户是否已经登录

I have everything working, except for one thing: determining at init time whether the user is already logged in.

目前,我的code是这样的:

Currently, my code looks like this:

angular.module( 'MyModule', [ 'ngResource', 'ngRoute' ] )
    .run( [ '$rootScope', '$location', 'AuthService', function( $rootScope, $location, AuthService ) {

        /**
         * Initialize AuthService. This will cause it to make a REST call
         * to GET /api/current_user. That endpoint will return either a JSON
         * representation of the logged-in user, or a 401 Unauthorized.
         * Either way, AuthService will cache the results, which can be
         * accessed by calling AuthService.getUser().
         */
        AuthService.init();

        /**
         * Listen for route changes. If the user tries to change to a route
         * that requires login, but the user isn't logged in, then redirect
         * to the login page.
         */
        $rootScope.$on( '$routeChangeStart', function( event, next, current ) {

            if ( next.$$route.requiresLogin && AuthService.getUser() === null ) {
                $location.path( '/login' );
            }

        } );

    } ] );

显然,这里有一个问题:调用 AuthService.init()将需要一段时间才能完成(因为它必须做出一个HTTP调用),但第一个 $ routeChangeStart 事件会尽快 .RUN火()完成。

Obviously, there's a problem here: the call to AuthService.init() will take time to complete (since it must make an HTTP call), but the first $routeChangeStart event will fire as soon as .run() completes.

所以,即使用户已经登录, AuthService 将不知道着呢,用户将得到重定向到登录页面。

So, even if the user is already logged in, AuthService won't know that yet, and the user will get "redirected" to the login page.

我可以调整AuthService.init()返回一个承诺,并据此重构这个code:

I could tweak AuthService.init() to return a promise, and refactor this code accordingly:

angular.module( 'MyModule', [ 'ngResource', 'ngRoute' ] )
    .run( [ '$rootScope', '$location', '$route', 'AuthService', function( $rootScope, $location, $route, AuthService ) {

        /**
         * Initialize AuthService. This will cause it to make a REST call
         * to GET /api/current_user. That endpoint will return either a JSON
         * representation of the logged-in user, or a 401 Unauthorized.
         * Either way, AuthService will cache the results, which can be
         * accessed by calling AuthService.getUser().
         */
        AuthService.init(
            function() {

                // Make sure the user is allowed to view the initial route
                enforce_login( $route.current );

                // Also check when the user tries to navigate to another route
                $rootScope.$on( '$routeChangeStart', function( event, next, current ) {
                    enforce_login( next );
                } );

            }
        );

        function enforce_login( theRoute ) {
            if ( theRoute.$$route.requiresLogin && AuthService.getUser() === null ) {
                $location.path( '/login' );
            }
        }

    } ] );

不过,这是有问题的太:如果HTTP调用 GET / API / CURRENT_USER 需要一两秒钟才能完成,并且用户已加载的保护途径,那么应用程序将短暂显示受保护的路径,重定向到登录页面之前。

However, this is problematic too: if the HTTP call to GET /api/current_user takes a second or two to complete, and the user has loaded a protected route, then the app will briefly display the protected route, before redirecting to the login page.

我真正需要做的是的延迟的加载/直到AuthService初始路线的渲染有机会来确定用户的登录状态。

What I really need to do is delay loading/rendering of the initial route until AuthService has had a chance to determine the user's login state.

有没有对这个问题的典型做法?所有我见过的角认证教程假设你AuthService将能的同步的确定用户的登录状态。但他们并不真正解释它是如何应该做的。

Is there a typical approach to this problem? All of the Angular authentication tutorials I've seen assume that your AuthService will be able to synchronously determine the user's login state. But they don't really explain how it's supposed to do that.

的一个解决方案是消除需要使在所述第一地点的异步调用。例如,我可以从一个单独的负载我AuthService <脚本> 标签,就像这样:

One solution is to eliminate the need to make an asynchronous call in the first place. For example, I could load my AuthService from a separate <script> tag, like this:

<script src="MyModule.min.js"></script>
<script src="AuthService.js.php"></script>

...和 AuthService.js.php 将动态地生成它已经知道在初始化角时在用户是否登录JS文件。

...and AuthService.js.php would dynamically generate a JS file which already knows at Angular init time whether or not the user is logged in.

不过,这种感觉真的hackish的,这对夫妻的客户端应用程序到服务器端执行,使得AuthService.js不可缓存,并且一般是杂牌。

However, this feels really hackish—it couples the client-side app to the server-side implementation, makes AuthService.js uncacheable, and is generally a kludge.

所以,我的问题是:我如何才能最好地检查用户的登录状态下角初始化时,的的角度计算并呈现初始路径

So, my question is: how can I best check the user's login state at Angular init time, before Angular evaluates and renders the initial route?

推荐答案

使用

resolve: { AuthService: 'AuthService' }

(或解决其他任何东西,从权威性的服务回报承诺)作为所有访问控制的路径依赖,看到的手动

倾听 $ routeChangeError 重定向到登录路线。

Listen for $routeChangeError to redirect to login route.

这篇关于在初始化角时的最佳做法/模式进行用户身份验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆