2015-09-26 40 views
0

我有一個由我自己構建的AngularJs用戶身份驗證及其工作。一切工作正常。我可以登錄,可以檢查用戶是否可以訪問特定頁面等。除了事實上,令牌身份驗證我只在與WebApp進行的第二次交互時運行。例如,如果我更改localStorage上的某些數據(我要保存用戶數據)並嘗試訪問管理頁面,例如,我將能夠訪問該頁面,但在下一頁互動,然後我會被踢出頁面並回到登錄過程。AngularJs用戶身份驗證只發生在第二次交互

可能發生了什麼? 這是我使用的代碼:

app.js

function getUser() { 
    userinfo = JSON.parse(localStorageService.get("user")); //convert string to json 
    $scope.userData = userinfo; //Display purpouso only; 
}; 
function checkToken() { 
    var userCheckToken = JSON.parse(localStorageService.get("user")); 
    $http.post('dist/php/db.php?action=token', userCheckToken) 
    .success(function(res){ 
     userToken = res; 
    }).error(function(err){ 
     alert(feedbackError); 
    }); 
}; 

$rootScope.$on('$stateChangeStart', function(e, to) { 
    if (to.data && to.data.requireLogin) { 
     getUser(); 
     checkToken(); 
     if (!userinfo) { 
      e.preventDefault(); 
      $state.go('login'); 
      alert("You need to be loggedin"); 
     } 
     else if (userinfo && !userToken) { 
      e.preventDefault(); 
      userInfo = false; 
      $state.go('login'); 
      localStorageService.clearAll(); 
      alert('Authentication failed'); 
     } 
    } 
}); 

同樣的事情發生在一個單獨的function。假設我在頁面上有一個重要的功能,所以只有管理員可以執行該功能。我也正在檢查該進程的身份驗證,但它發生在同一事件上,僅在第二次交互時發生。

功能:

$scope.debugTk = function() { 
    checkToken(); 
    if (!userToken) { 
     alert('Authentication failed'); 
    } else { 
     $http.get('dist/php/db.php?action=debugTk') 
     .success(function(res){ 
      $scope.resultDebug = res; 
     }).error(function(err){ 
      alert(feedbackError); 
     }); 
    } 
} 
+0

'checkToken()'是異步的。在這種情況下,除了回調 – charlietfl

+0

@charlietfl之外,您不能在它後面查找'userToken',我應該怎麼做? – celsomtrindade

+2

這會通過在路由器父狀態中使用解析來簡化很多。然後,如果解決方案被拒絕,則該父項下的子狀態不可訪問 – charlietfl

回答

2

爲charlieftl已經說了,你checkToken函數使用一個XHR請求默認情況下是異步的。你需要用依賴的checkToken執行與這樣的回調一切:

function getUser() { 
    userinfo = JSON.parse(localStorageService.get("user")); //convert string to json 
    $scope.userData = userinfo; //Display purpouso only; 
}; 
function checkToken() { 
    var userCheckToken = JSON.parse(localStorageService.get("user")); 
    $http.post('dist/php/db.php?action=token', userCheckToken) 
    .success(function(res){ 
     return res; // returns inside a promise make them chainable. 
    }).error(function(err){ 
     return feedbackError; 
    }); 
}; 

$rootScope.$on('$stateChangeStart', function(e, to) { 
    if (to.data && to.data.requireLogin) { 
     getUser(); 
     if (!userinfo) { 
      e.preventDefault(); 
      $state.go('login'); 
      alert("You need to be loggedin"); 
     } else { 
      checkToken().then(function(userToken){ // this gets executed after checkToken() succeeds. 

       if (!userToken) { 
        // this won't work here: e.preventDefault(); 
        userInfo = false; 
        $state.go('login'); 
        localStorageService.clearAll(); 
        alert('Authentication failed'); 
       } 
      }, function(err){ 
       // this gets called when your .error method returns an error 
       // eg. the HTTP request failed. 
      }); 
     } 
    } 
}); 

debugTk功能看起來像這樣那麼: $ scope.debugTk =函數(){ checkToken()即可。 (函數(){// 成功 },函數(){// 錯誤

 if (!userToken) { 
      alert('Authentication failed'); 
     } else { 
      $http.get('dist/php/db.php?action=debugTk') 
      .success(function(res){ 
       $scope.resultDebug = res; 
      }).error(function(err){ 
       alert(feedbackError); 
      }); 
     } 
    }); 
} 

瞭解更多關於此承諾:https://github.com/wbinnssmith/awesome-promises

編輯:e.preventDefault()呼叫在承諾內不起作用,您需要更改代碼以適應承諾。我不會把這樣的東西包裝到$ stateChangeStart事件中,而是使用一個服務來處理所有的auth東西。

+0

越來越近,但防止'$ http'回調中的缺省值太遲而無法阻止狀態變化 – charlietfl

+0

感謝該捕獲。我編輯答案:)。甚至沒有注意到preventDefault調用。 –

+0

謝謝@praszyk我理解這個概念,但我是編程新手,所以我仍然需要學習。有一件事,我有這個錯誤:'不能讀取屬性'然後'在這部分undefined'在這裏:'checkToken()。然後(函數(userToken){'任何想法爲什麼? – celsomtrindade

1

根據AngularJS文檔:

的$ HTTP遺留承諾的方法成功和錯誤已被棄用。改爲使用標準然後方法。如果$ httpProvider.useLegacyPromiseExtensions設置爲false,那麼這些方法將拋出$ http/legacy錯誤。

關於你的問題,因爲它說checkToken函數是異步的,所以你每次調用這個函數都需要使用promises。從checkToken函數返回$http.post結果:

function checkToken() { 
    var userCheckToken = JSON.parse(localStorageService.get("user")); 
    return $http.post('dist/php/db.php?action=token', userCheckToken).then(
    function (res) { 
     userToken = res; 
    }, 
    function (err) { 
     alert(feedbackError); 
    }); 
}; 

,然後用它作爲普通的承諾:

$scope.debugTk = function() { 
    checkToken().then(function(){ 
    if (!userToken) { 
     alert('Authentication failed'); 
    } else { 
     //..... 
    } 
    }); 
} 
+0

謝謝sr!隨着你的答案和來自@praszyk的回答我可以把它放在一起並使它工作,到目前爲止唯一的問題是e.preventDefault()方法,就像praszyk說的那樣,它不會在promise結果中工作。我可以使用它,所以用戶不會去他正在嘗試去執行或正在執行他正在執行的功能的頁面嗎? – celsomtrindade

+0

我認爲答案是在ui-router文檔中,如果它是'ngRoute',我會對於函數,我認爲你可以使用函數'executeIfHaveAccess(action)'(絕對不是函數的專有名稱),它將檢查用戶是否可以執行此操作,或者不是。 –

+0

如果我沒有錯,那會(這是)[https://github.com/ angular-ui/ui-router/wiki#resolve],對不對?但是,我必須移動'.state'內的auth檢查才能使其正常工作? – celsomtrindade