2016-01-25 119 views
1

我正在編寫代碼爲AngularSPA(單頁應用程序)。使用UI路由器和令牌在AngularJS中重定向

  • 在後端把它連接到寫在Java發動機,其承擔了大部分的處理(與我不關心)。

  • 我正在使用UI Router來做路由。

問題

然而,有一個棘手的情況,我不能夠完成。

  • 登錄時,我進行了一個API調用,返回格式爲JSON的響應。

  • 如果我的通話成功(即登錄憑證匹配),我在返回的JSON中得到一個令牌,它基本上是一個符號,字母和數字組合的字符串。

  • 我將它保存在我的rootscope中,然後像訪問$ rootScope.myToken一樣訪問它。

  • 然後我在隨後的API調用中使用相同的標記。

現在我想在AngularJS做的是將用戶重定向到登錄頁面,如果他/未登錄她,並試圖通過直接在地址欄中輸入它訪問某些網址。

我在這裏找到了一個相當簡單的方法Redirect on all routes to login if not authenticated。但是我無法用我的令牌來實現這一點。

問題

我應該怎麼做才能讓與令牌這項工作?除了這個答案以外的任何其他建議也是受歡迎的。 PS:我已經嘗試了多種方法在stackoverflow上,我發現它們不是在我的上下文中工作或過於複雜的目的。

更新:我可以成功實施Simon H的答案在我的代碼中。然而,我面臨的問題是,這將只會重新定向,因爲我希望在登錄後至少有一次我的應用程序退出。如果我嘗試直接通過URL訪問頁面而無需至少登錄和登出一次,則此方法失敗,我仍然可以訪問該頁面。有小費嗎?

回答

1

有很多的教程在網上的角度和智威湯遜

我使用的那些開發沿着你想要的東西線。代碼的他們關鍵部分是在配置

$httpProvider.interceptors.push(function($q, $location, $localStorage, $injector) { 
    return { 
     'request': function (config) { 
      config.headers = config.headers || {}; 
      if ($localStorage.token) { 
       config.headers.Authorization = 'Bearer ' + $localStorage.token; 
      } 
      return config; 
     }, 
     'responseError': function(response) { 
      /* 401, unauthorised: 
       - bad username/password 
       - token expired 
       403, forbidden - notAdmin 
      */ 
      // if(response.status === 401 || response.status === 403) { 
      if(response.status === 401) { 
       console.log("app.js: httpInterceptor caught 40x:", response); 
       $injector.get('$state').go('login'); 
      } 
      // Replace reponse with rejected promise to prevent rest of execution 
      return $q.reject(response); 
     } 
    }; 
+0

我是一個Web開發的初學者,從我看過的內容來看,JWT相當複雜。就我而言,令牌只不過是一個隨機生成的字符串,正如我在問題中提到的那樣。也許它甚至不是一個適當的標記,我們簡單地稱它爲一個標記。這會繼續嗎? – theHeman

+0

此外,我有點困惑這段代碼應該在哪裏?在具有我的路由代碼的'app.js'文件中,我應該將它放在路由配置中嗎?還是外面呢? – theHeman

+0

**更新:**我可以在我的代碼中成功實現這一點。然而,我面臨的問題是,這將只會重新定向,因爲我希望在登錄後至少有一次我的應用程序退出。如果我嘗試直接通過URL訪問頁面而無需至少登錄和登出一次,則此方法失敗,我仍然可以訪問該頁面。有小費嗎? – theHeman

0

大概真的晚了(因爲Angular2的了,但是我現在還在,如果還有人仍在使用1回答。x),但是我在Node上發送JWT和Angular使用它,並且我使用UI路由器完成了自己的工作。 西蒙的解決方案將工作,但我儘量不要觸摸rootScope。

我實現了3個東西來讓它工作。授權服務,ngStorage模塊和Ui路由器的狀態的解析屬性。

ngStorage

這是一個公開$的localStorage和sessionStorage的$模塊。您可以向其中添加任何對象,並將其設置在瀏覽器中,直到您清除它。

UI路由器狀態的決心

1.x中的官方文檔指出,決心是映射到一個函數,將觸發狀態,即使被初始化之前的屬性。因此,這是一個你可以做狀態依賴的微觀配置的地方,它也可以承諾。

授權廠

這是一個工廠,有3個服務。登錄,註銷並經過認證。登錄服務在成功時將令牌設置在$ localStorage中。在它的依賴注入中,我使用ngStorage的$ localStorage服務和$ http以及其他注入了它。


現在我解釋我是怎麼做到的。

我總是將我的默認狀態指向我的家鄉,而不是登錄狀態。

取代使用rootcope,我使Authorization Factory的登錄服務發佈到服務器的登錄端點(將給我一個新標記的終點)。一旦我收到令牌,我將它設置爲$ localStorage作爲我的令牌。

然後,根據我的家庭狀態,我調用授權工廠的isAuthenticated服務,該服務只檢查令牌是否設置在$ localStorage中。如果不是,則返回false。如果它返回false,我可以通過$ state.go('login')將主狀態重定向轉換爲我的登錄狀態;

我得到的是,在每一個http調用應用程序範圍內,我都可以在控制器中注入Authorization的isAuthenticated服務並讓它檢查令牌(哪個登錄服務已獲得,哪個已驗證也可以訪問,因爲它們在同一工廠)。如果令牌存在,我提取該令牌並將其與我的數據一起發送到服務器。然後,我的服務器可以執行額外的令牌驗證,例如檢查它的到期時間和東西以及401s或200s的響應。

現在這可能聽起來很生氣,看起來好像不是乾的。但我想說,我在一個根父母國家做了所有這些事情,並且將所有其他國家都視爲兒童狀態。父母是抽象的,因此可以做決定,並且不需要初始化狀態。家可以是默認的非抽象狀態。

我試圖遠離rootScopes和$手錶和東西,我把它們作爲最後的手段永遠。乾杯!