为什么AngularJS服务重新初始化路由重加载时? [英] Why is AngularJS service re-initialized when route is re-loaded?

查看:426
本文介绍了为什么AngularJS服务重新初始化路由重加载时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是AngularJS服务注入两个独立的模块。这导致该服务时,第二个模块调用它单独重新初始化。我已经使用Firefox的调试,以确认该模块正在重新初始化。我怎样才能避免这个问题?

下面是具体情况:

这是AngularJS应用程序使用身份验证服务被称为模块 AUTH 来管理认证的担忧。在 AUTH 服务导入到其管理的安全 /消息访问的消息模块路线和 AUTH 也导入到其中同时管理登录/注册,也是一个导航模块在用户的浏览器的导航链接的可见内容。用户能够成功登录使用链接到导航模块的GUI工具,然后被成功重定向到安全 /消息路线作为身份验证的用户,因为 auth.authenticated1 auth.authenticated2 属性设置为真正只是重定向到 /消息之前出现。

不过,Firefox的调试器证实,问题在于,当用户刷新浏览器重新加载 /消息 URL模式, AUTH 模块重新初始化,设置 auth.authenticated1 的价值观和 auth.authenticated2 回假,从而给用户,他们还没有登录的消息,即使他们在某一时刻已登录使用用户提供的有效凭证之前。 需要什么具体的改变code至作出以下,这样用户没有注销的页面重新加载?

我要AngularJS code,检查pre-现有的 auth.authenticated2 值当 /消息路由加载或重载。如果 auth.authenticated2 = FALSE ,那么用户得到一个消息,说他们被注销。但是,如果 auth.authenticated2 = TRUE ,我希望用户能够看到安全内容在 /消息路线。 我不希望 auth.authenticated2 来自动重新设置为重装后的路线,现在的方法是。

下面是 message.html 的code,其中包含了 /消息路由GUI元素

 < D​​IV NG秀=authenticated2()>
    < H1>安全内容< / H1>
    < D​​IV>
        < P>安全内容使用REST API的认证用户从服务器提供< / P>
    < / DIV>
< / DIV>
< D​​IV NG-秀= GTauthenticated2()!;
    < H1>您还没有登录< / H1>
< / DIV>

下面是 message.js 的code这是一个管理的消息模块控制器在 /消息路线:

  angular.module('消息',['权威性'])。控制器('消息',函数($范围,$ HTTP,$ SCE,AUTH){    $ scope.authenticated2 =功能(){
        返回auth.authenticated2;
    }    //其他code从这里省略留在主题服务器调用REST API的});

下面是code为导航模块,这也注入了 AUTH 服务:

  angular.module('导航',['ngRoute','权威性'])。控制器('导航',函数($范围,$路线,权威性,$ HTTP, $ routeParams,$位置){    从旧的导航模块//; $ scope.credentials = {}
    $ scope.leadresult =空白;
    $ scope.processStep =开始;
    $ scope.uname =空白;
    $ scope.wleadid =初始空白值;
    $ scope.existing =空白;    $ scope.tab =功能(路线){
        返回$ route.current&放大器;&安培;路线=== $ route.current.controller;
    };    $ scope.authenticated1 =功能(){
        返回auth.authenticated1;
    }    $ scope.authenticated2 =功能(){
        返回auth.authenticated2;
    }    $ scope.login =功能(){
        auth.authenticate1($ scope.credentials,功能(authenticated1){
            //一堆东西,做1级认证,在这里是不相关
        })
    }    $ scope.logout = auth.clear;    //一些其他的方法来管理在用户注册过程的注册形式,这在这里被省略,因为它们是题外话    $ scope.pinForm =功能(的isValid){//此方法在登录完成用户认证
        如果(的isValid){
            $ scope.resultmessage.webleadid = $ scope.wleadid;
            $ scope.resultmessage.name = $ scope.uname;
            $ scope.resultmessage.existing = $ scope.existing;
            VAR funcJSON = $ scope.resultmessage;
            auth.authenticate2(funcJSON,功能(authenticated2){
                如果(authenticated2){
                    $ location.path('/消息');
                    $ $范围适用于(); //此行成功地重新引导用户`/ message`航线登录的有效凭据
                }
            });
        }
    };    ($范围。在$('$ viewContentLoaded',功能){
        //方法,使一个不相关的呼叫为匿名用户REST服务
    });});

下面是code在 auth.js AUTH 服务:

  angular.module('权威性',[])。工厂('权威性',函数($ rootScope,$ HTTP,$位置){    VAR AUTH = {        authenticated1:假的,
        authenticated2:假的,
        usrname:'',        LOGINPATH:/登录,
        logoutPath:'/注销,
        HOMEPATH:'/消息,
        路径:$ location.path()        authenticate1:​​功能(凭证,回调){
            VAR标题=凭证和放大器;&安培; credentials.username? {
                授权:基本+ BTOA(credentials.username +:+ credentials.password)
            }:{};            $ http.get('用户',{
                标题:标题
            })。成功(功能(数据){
                如果(data.name){auth.authenticated1 = TRUE; }
                其他{auth.authenticated1 = FALSE; }
                回调和放大器;&安培;回调(auth.authenticated1);
            })错误(函数(){
                auth.authenticated1 = FALSE;
                回调和放大器;&安培;回调(假);
            });
        },        authenticate2:功能(funcJSON,回调){
            $ http.post('/签销',funcJSON)。然后(功能(响应){
                如果(response.data.content =='pinsuccess'){
                    auth.authenticated2 = TRUE;
                    回调和放大器;&安培;回调(auth.authenticated2);
                }其他{
                    auth.authenticated2 = FALSE;
                    auth.authenticated2 = FALSE;
                    回调和放大器;&安培;回调(假);
                }
            });
        },        明确:功能(){
            $ location.path(auth.loginPath);
            auth.authenticated1 = FALSE;
            auth.authenticated2 = FALSE;
            。$ http.post(auth.logoutPath,{})成功(函数(){的console.log(注销成功);
            })错误(功能(数据){执行console.log(注销失败);});
        },        初始化:功能(HOMEPATH,LOGINPATH,logoutPath){
            auth.homePath = HOMEPATH;
            auth.loginPath = LOGINPATH;
            auth.logoutPath = logoutPath;
        }
    };
    返回权威性;
});

routeProvider 由主 JS管理文件的应用程序,这是 hello.js 键,如下:

  angular.module('你好',['ngRoute','权威性','家','消息','public1上','导航'])
    的.config(        功能($ routeProvider,$ httpProvider,$ locationProvider){            $ locationProvider.html5Mode(真); / *此行是3个地方,我们集天然网址,一个遥控器默认的#* /            $ routeProvider.when('/',{
                templateUrl:JS /家庭/ home.html做为',
                控制器:家
            })时​​,('/消息',{
                templateUrl:JS /消息/ message.html',
                控制器:'消息'
            })。当('/ public1上',{
                templateUrl:JS / public1上/ public1.html',
                控制器:'p​​ublic1上
            })时​​,('/注册',{
                templateUrl:JS /导航/ register.html',
                控制器:导航
            })。除此以外('/');            $ httpProvider.defaults.headers.common ['X-要求-随着'] ='XMLHtt prequest';        })。运行(功能(AUTH){            //初始化验证模块的主页,登录/注销路径
            // 分别
            auth.init('/ checkpin','/登录','/注销');        });


解决方案

不是一个完整的答案作为,确切code改变这里。但足以让建很好的东西。

您应该没有明确使用你的身份验证服务中唯一布尔值。据我所看到的,你不使用你从服务器验证成功后收到任何数据。所以每当你刷新,一切都失去了。你不必在你的code东西从刷新恢复。

在理想情况下,你应该有类似令牌或饼干。该cookie将被保存,并且可以在刷新后可以恢复,因此在启动身份验证服务,可以检查该cookie的存在。

您还可以保存,可用于访问索引资料或类似的东西里面的API令牌。正如我之前所说的,在身份验证服务的启动时间,你必须检查该令牌的存在。

如果您需要了解更多信息,检查的oauth2。即使是OAuth2用户不是一个认证API,但授权API,密码交付式的东西,你可以使用。为了得到一个想法如何建立一个坚实的制度。其它授权类型大多只注重OAuth的授权方。

由于OP索要code这里是:

 时creating_service:
  如果存在(饼干)或存在(标记)和有效(饼干)或有效的(标记):
     mark_service_as_logged_in()

如果伪$ ​​C $ C胜于言。

An AngularJS service is injected into two separate modules. This is causing the service to re-initialize separately when the second module calls it. I have used the FireFox debugger to confirm that the module is being re-initialized. How can I avoid this problem?

Here is the specific case:

An AngularJS app uses an authentication service in a module called auth to manage authentication concerns. The auth service is imported into a message module which manages access to the secure /message route and auth is also imported into a navigation module which manages both login/registration and also the visible contents of the navigation links in the user's browser. A user is able to successfully login using the GUI tools linked to the navigation module, and is then successfully redirected to the secure /message route as an authenticated user because the auth.authenticated1 and auth.authenticated2 properties are set to true just before the redirect to /message occurs.

However, the FireFox debugger confirms that the problem is that, when the user refreshes the browser to reload the /message url pattern, the auth module is re-initialized, setting the values of auth.authenticated1 and auth.authenticated2 back to false, and thus giving the user a message that they are not logged in, even though they were logged in a moment before using valid credentials provided by the user. What specific changes need to be made to the code below so that the user is NOT logged out on page re-load?

I want the AngularJS code to check the pre-existing value for auth.authenticated2 when the /message route is loaded or reloaded. If auth.authenticated2=false, then the user gets a message saying they are logged out. But if auth.authenticated2=true, I want the user to be able to see the secure content at the /message route. I DO NOT want auth.authenticated2 to be automatically re-set to false upon reloading the route, the way it is now.

Here is the code in message.html which contains the GUI elements for the /message route:

<div ng-show="authenticated2()">
    <h1>Secure Content</h1>
    <div>
        <p>Secure content served up from the server using REST apis for authenticated users.</p>
    </div>
</div>
<div ng-show="!authenticated2()">
    <h1>You are not logged in.</h1>
</div>

Here is the code in message.js which is the controller for the message module that manages the /message route:

angular.module('message', ['auth']).controller('message', function($scope, $http, $sce, auth) {

    $scope.authenticated2 = function() {
        return auth.authenticated2;
    }

    //Other code calling REST apis from the server omitted here to stay on topic

});

Here is the code for the navigation module, which also injects the auth service:

angular.module('navigation', ['ngRoute', 'auth']).controller('navigation', function($scope, $route, auth, $http, $routeParams, $location) {

    $scope.credentials = {};//from old navigation module
    $scope.leadresult = "blank";
    $scope.processStep = "start";
    $scope.uname = "blank";
    $scope.wleadid = "initial blank value";
    $scope.existing = "blank";

    $scope.tab = function(route) {
        return $route.current && route === $route.current.controller;
    };

    $scope.authenticated1 = function() {
        return auth.authenticated1;
    }

    $scope.authenticated2 = function() {
        return auth.authenticated2;
    }

    $scope.login = function() {
        auth.authenticate1($scope.credentials, function(authenticated1) {
            //a bunch of stuff that does level 1 authentication, which is not relevant here
        })
    }

    $scope.logout = auth.clear;

    //some other methods to manage registration forms in a user registration process, which are omitted here because they are off-topic

    $scope.pinForm = function(isValid) {//this method finishes authentication of user at login
        if (isValid) {
            $scope.resultmessage.webleadid = $scope.wleadid;
            $scope.resultmessage.name = $scope.uname;
            $scope.resultmessage.existing = $scope.existing;
            var funcJSON = $scope.resultmessage;        
            auth.authenticate2(funcJSON, function(authenticated2) {
                if (authenticated2) {
                    $location.path('/message');
                    $scope.$apply();//this line successfully re-directs user to `/message` route LOGGED IN with valid credentials
                }
            });
        }
    };

    $scope.$on('$viewContentLoaded', function() {
        //method that makes an unrelated call to a REST service for ANONYMOUS users
    });

});

Here is the code for the auth service in auth.js:

angular.module('auth', []).factory( 'auth', function($rootScope, $http, $location) {

    var auth = {

        authenticated1 : false,
        authenticated2 : false,
        usrname : '',

        loginPath : '/login',
        logoutPath : '/logout',
        homePath : '/message',
        path : $location.path(),

        authenticate1 : function(credentials, callback) {
            var headers = credentials && credentials.username ? {
                authorization : "Basic " + btoa(credentials.username + ":" + credentials.password)
            } : {};

            $http.get('user', {
                headers : headers
            }).success(function(data) {
                if (data.name) { auth.authenticated1 = true; } 
                else { auth.authenticated1 = false; }
                callback && callback(auth.authenticated1);
            }).error(function() {
                auth.authenticated1 = false;
                callback && callback(false);
            });
        },

        authenticate2 : function(funcJSON, callback) {
            $http.post('/check-pin', funcJSON).then(function(response) {
                if(response.data.content=='pinsuccess'){
                    auth.authenticated2=true;
                    callback && callback(auth.authenticated2);
                }else {
                    auth.authenticated2=false;
                    auth.authenticated2 = false;
                    callback && callback(false);
                }
            });
        },

        clear : function() {
            $location.path(auth.loginPath);
            auth.authenticated1 = false;
            auth.authenticated2 = false;
            $http.post(auth.logoutPath, {}).success(function() { console.log("Logout succeeded");
            }).error(function(data) { console.log("Logout failed"); });
        },

        init : function(homePath, loginPath, logoutPath) {
            auth.homePath = homePath;
            auth.loginPath = loginPath;
            auth.logoutPath = logoutPath;
        }
    };
    return auth;
});

The routeProvider is managed by the main js file for the app, which is hello.js and is as follows:

angular.module('hello', [ 'ngRoute', 'auth', 'home', 'message', 'public1', 'navigation' ])
    .config(

        function($routeProvider, $httpProvider, $locationProvider) {

            $locationProvider.html5Mode(true);/* This line is one of 3 places where we set natural urls to remote the default # */

            $routeProvider.when('/', {
                templateUrl : 'js/home/home.html',
                controller : 'home'
            }).when('/message', {
                templateUrl : 'js/message/message.html',
                controller : 'message'
            }).when('/public1', {
                templateUrl : 'js/public1/public1.html',
                controller : 'public1'
            }).when('/register', {
                templateUrl : 'js/navigation/register.html',
                controller : 'navigation'
            }).otherwise('/');

            $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

        }).run(function(auth) {

            // Initialize auth module with the home page and login/logout path
            // respectively
            auth.init('/checkpin', '/login', '/logout');

        });

解决方案

Not a complete answer as in, exact code to change here. But enough to get something built nicely.

You shouldn't explicitly use only boolean values inside your auth service. As far as I can see, you're not using any data that you're receiving from the server after a successful authentication. So whenever you refresh, everything is lost. You don't have anything in your code to recover from a refresh.

Ideally, you should have something like a token or a cookie. The cookie will be saved and can be recovered after a refresh, so while starting the auth service, you can check for the existence of that cookie.

You could also save a token that can be used to access an API inside an indexedDB or something like that. Just as I said before, during boot time of the auth service, you'll have to check for the existence of that token.

If you need more information, check for Oauth2. Even though Oauth2 isn't an Authentication API but an authorization API, the password grant type is something you could use. To get an idea how to build a solid system. The other grant types are mostly only focused on the authorization side of OAuth.

Because OP ask for code here it is:

when creating_service:
  if exists(cookie) or exists(token) and valid(cookie) or valid(token):
     mark_service_as_logged_in()

If pseudo code is better than words.

这篇关于为什么AngularJS服务重新初始化路由重加载时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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