2014-11-21 30 views
3

所以我有這個功能,我run在angularjs(運行AngularJS v1.2.26)如何使用ui-router檢查身份驗證並自動重定向到登錄狀態?

.run(function(....) { 
    authService.authCheck(); 

    $rootScope.$on('$routeChangeStart', function(event, next, current) { 
     if (next.requireLogin) { 
      if (!authService.isLoggedIn()) { 
       $location.path('/login'); 
       event.preventDefault(); 
      } 
     } 
    }); 

})... 

時直接訪問需要身份驗證例如一個網址http://127.0.0.1:8080/secret,函數總是重定向到登錄路徑,清楚地在調試一段時間後,它總是評估爲false。當訪問默認頁面,然後去指定的路線它運行沒有任何問題。

這是一部分我authService

this.authCheck = function() { 
    $http({ 
     method: 'PUT', 
     url: '/api/login' 
    }). 
    success(function(data, status, headers, config) { 
     if (status === 200) { 
      userIsAuthenticated = true; 
     } else { 
      userIsAuthenticated = false; 
     } 
     $rootScope.loginStatus = userIsAuthenticated; 
    }). 
    error(function(data, status, headers, config) { 
     userIsAuthenticated = false; 
     $rootScope.loginStatus = userIsAuthenticated; 
    }); 
}; 

this.isLoggedIn = function() { 
    return userIsAuthenticated; 
}; 

所以每次我有!authService.isLoggedIn()一個破發點時間,我看到它的計算結果爲假,即使在運行塊中的函數試圖到達$rootScope.$on之前,它驗證功能。

究竟是什麼阻止了userIsAuthenticated變量的持續狀態?

回答

6

.authCheckauthService是異步的,這意味着,直到它實際上完成首次userIsAuthenticated將不會被設置爲true。如果您現在遵循了現在的路線,則必須編寫一些更復雜的代碼,以便等待支票尚未完成並重新定向。但是,這是一個混亂的次優選項。

最好的辦法是讓ui-router爲你解決這個問題。爲需要登錄的所有國家創建共同的祖先狀態,例如'session'。然後使用resolve選項使該狀態的解析等待您的身份驗證檢查。如果未通過身份驗證,請創建特定的狀態傳輸拒絕錯誤,您可以在其他位置捕獲並執行操作(重定向到登錄)。

.state('session', { 
    resolve: { 
     authentication: ['authService', '$q', function (authService, $q) { 
      return authService.checkAuthentication().then(function() { 
       if (!authService.isAuthenticated) { 
        return $q.reject({ 
         notAuthenticated: true 
        }); 
       } 
      }); 
     }] 
    }, 
    // ... 
}) 
.state('secret', { 
    parent: 'session', 
    // ... 
}); 

然後

$rootScope.$on('$stateChangeError', function (_0, _1, _2, _3, _4, error) { 
    if (error.notAuthenticated) { 
     $state.go('login'); 
    } 
}); 

(你需要正確地從認證檢查返回以及)

checkAuthentication: function() { 
    return $http({...}) 
     .success(...) 
     .error(...); 
} 
+0

所以即使我沒有使用承諾,調用('$ http')仍然被認爲是異步調用?感謝您的回覆,我會在家時嘗試一下。 – ymg 2014-11-24 08:02:18

+0

'$ http'調用總是異步的,以防止鎖定瀏覽器。並且你使用承諾 - 返回值是一個承諾,擴展了特殊函數'success'和'error' :)。對於我的示例工作,你只需要返回整個事情。 – hon2a 2014-11-24 08:04:33

+0

我明白了。非常感謝真棒的答案! – ymg 2014-11-24 08:08:38

0

您是否允許應用程序發送來自/ secret的請求? 它可能會阻止你從那裏發出的任何請求,因此將您重定向到登錄

+0

'/ secret'檢查的身份驗證令牌(會話)與正在做的就是正確的特權。問題是我可以訪問'/ secret'並從那裏發佈一個有效的表單,並且服務器可以正常工作,但是最初的請求導致了我說的問題。 – ymg 2014-11-24 07:57:04

+0

我知道問題是應用程序在認證完成之前更改根目錄!你可以繞過這個問題,通過使用一個服務在事件$ routeChangeStart 中激活代碼而不使用它(這是最快的解決方案,如果你必須儘快完成這個功能) – 2014-11-24 08:03:10

相關問題