2016-01-18 93 views
-1

AngularJS服務被注入到兩個獨立的模塊中。這會導致服務在第二個模塊調用它時分別重新初始化。我已經使用FireFox調試器來確認模塊正在重新初始化。我怎樣才能避免這個問題?爲什麼在重新加載路由時AngularJS服務會重新初始化?

以下是具體情況:

的AngularJS應用程序使用一個名爲auth模塊中的認證服務管理認證的擔憂。 auth服務被導入到message模塊中,該模塊管理對安全/message路由的訪問,並且auth也被導入navigation模塊,其管理登錄/註冊以及用戶瀏覽器中的導航鏈接的可見內容。用戶能夠使用鏈接到navigation模塊的GUI工具成功登錄,然後作爲經過驗證的用戶成功重定向到安全/message路由,因爲auth.authenticated1auth.authenticated2屬性在重定向到/message之前設置爲true

然而,火狐調試確認的問題是,當用戶刷新的瀏覽器重新加載/message URL模式中,auth模塊被重新初始化,設定auth.authenticated1auth.authenticated2的值返回到錯誤的,因而即使用戶在使用用戶提供的有效憑證之前立即登錄,也會向用戶發送消息表明他們未登錄。 需要對下面的代碼進行哪些特定的更改,以便用戶在重新加載頁面時未被註銷?

我希望在/message路線被加載或重新加載AngularJS代碼來檢查預先存在的價值auth.authenticated2如果auth.authenticated2=false,則用戶會收到一條消息,指出他們已註銷。但是,如果auth.authenticated2=true,我希望用戶能夠看到/message路線上的安全內容。 我不想讓auth.authenticated2在重新加載路線時自動重新設置爲false,這是現在的方式。

這裏是message.html的代碼,其包含用於/message路線的GUI元素:

<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 

}); 

這裏是navigation模塊的代碼,它也注入了auth服務器冰:

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.jsauth服務的代碼:

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由主js文件的應用程序,這是hello.js和是如下進行管理:

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

     }); 

回答

0

不是一個完整的答案,在這裏改變的確切代碼。但足以讓一些建造得很好的東西。

您不應該在auth服務中顯式使用唯一的布爾值。據我所知,你沒有使用任何你在驗證成功後從服務器接收到的數據。所以無論什麼時候刷新,一切都會丟失。你的代碼中沒有任何東西可以從刷新恢復。

理想情況下,您應該有類似令牌或cookie的東西。該cookie將被保存並且可以在刷新後恢復,因此在啓動授權服務時,可以檢查該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() 

如果僞代碼勝於言。

+0

@CodeMed你問的是他爲你寫一個認證系統。這不是一件小事。它完全綁定到你的服務器。你可能會考慮對cookie /認證令牌做更多的研究,然後在遇到困難時詢問更狹義的問題。 –

+1

哇...請顯示代碼。 OP要求代碼希望你在開玩笑吧? –

+1

Cookie必須在服務器端完成。我很抱歉,你要求一個理論上的答案,因爲你似乎沒有任何想法認證如何工作。 –