为什么在重新加载路由时重新初始化AngularJS服务?

时间:2016-01-18 03:27:16

标签: javascript angularjs

AngularJS服务注入两个独立的模块。这导致服务在第二个模块调用时单独重新初始化。我使用FireFox调试器确认模块正在重新初始化。我该如何避免这个问题?

以下是具体案例:

AngularJS应用程序在名为auth的模块中使用身份验证服务来管理身份验证问题。 auth服务导入message模块,该模块管理对安全/message路由的访问,auth也导入navigation模块,该模块管理两个登录/ registration以及用户浏览器中导航链接的可见内容。用户可以使用链接到navigation模块的GUI工具成功登录,然后成功重定向到安全/message路由,因为auth.authenticated1和{{1在重定向到auth.authenticated2之前,属性设置为true

但是,FireFox调试器确认问题在于,当用户刷新浏览器以重新加载/message url模式时,/message模块将重新初始化,并设置{{1}的值1}}和auth返回false,从而向用户提供他们未登录的消息,即使他们在使用用户提供的有效凭据之前记录了一下。 需要对下面的代码进行哪些具体更改,以便用户不会在页面重新加载时退出?

我希望AngularJS代码在加载或重新加载auth.authenticated1路由时检查auth.authenticated2的预先存在的值。如果auth.authenticated2,那么用户收到一条消息,说明他们已退出。但是如果/message,我希望用户能够在auth.authenticated2=false路线上看到安全内容。 我不希望{%}}在重新加载路线时自动重新设置为auth.authenticated2=true,就像现在一样。

以下是/message中的代码,其中包含auth.authenticated2路由的GUI元素:

false

以下是message.html中的代码,它是管理/message路由的<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> 模块的控制器:

message.js

以下是message模块的代码,它还会注入/message服务:

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

});

以下是navigationauth服务的代码:

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
    });

});

auth由应用的主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; }); ,如下所示:

routeProvider

1 个答案:

答案 0 :(得分:0)

不是完整的答案,在此更改的确切代码。但足以让一些东西很好地构建。

您不应在auth服务中明确使用布尔值。据我所知,在成功进行身份验证后,您不会使用从服务器接收的任何数据。因此,无论何时刷新,一切都会丢失。您的代码中没有任何内容可以从刷新中恢复。

理想情况下,您应该拥有令牌或Cookie等内容。 cookie将被保存并在刷新后恢复,因此在启动auth服务时,您可以检查该cookie是否存在。

您还可以保存可用于访问indexedDB内部API的令牌或类似内容。正如我之前所说,在auth服务的启动时间内,您必须检查该令牌是否存在。

如果您需要更多信息,请检查Oauth2。尽管Oauth2不是身份验证API而是授权API,但您可以使用密码授予类型。了解如何构建一个可靠的系统。其他授权类型大多只关注OAuth的授权方。

因为OP在这里要求代码是:

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

如果伪代码比单词更好。