2016-12-01 122 views
3

我在尋找最好的架構解決方案。Angular JS身份驗證維護

我有以下的html:

<body ng-controller="individualFootprintController as $ctrl"> 
<div ng-hide="$ctrl.authenticated"> 
      <h1>Login</h1> 
      With Corporate Account: <a href="/login/corporate">click here</a> 
</div> 

和控制器:

function individualFootprintController($http) { 
     var self = this; 
     $http.get("/is_auth").success(function() { 
      self.authenticated = true; 
     }) 
      .error(function() { 
       self.authenticated = false; 
      } 
     ); 
} 

問題:

1)這是控制器具有這種邏輯適當的地方嗎?

2)我想要有實際的「is_authenticated」值。如果我只想觸發一次請求,如何才能做到這一點

回答

0

推測後端身份驗證需要某種實際的令牌。即您不只是在某處設置了一個true/false標誌並將其稱爲身份驗證,但爲了能夠與後端進行通信,您需要在請求中包含用戶名/密碼/ cookie /令牌,否則請求將被拒絕。

控制器是一個糟糕的地方來存儲這樣的事情,因爲控制器不是永久的。或者至少你不應該儘可能使它們永久。另外,將令牌存儲在控制器中不允許任何其他訪問。

  1. 無論您是否登錄,都應基於您是否擁有有效的身份驗證令牌。
  2. 此令牌必須存儲在規範的地方,最適合於這是一項服務。
  3. 其他服務從那裏獲取令牌,並根據令牌是否可用來決定應用程序當前是否「已登錄」。

的應當如何構建一個草圖:

app.service('AuthService', function() { 
    this.token = null; 
}); 

app.service('FooService', function (AuthService, $http) { 
    $http.get(..., AuthService.token, ...) 
}); 

app.controller('LoginStatusController', function (AuthService) { 
    Object.defineProperty(this, 'isLoggedIn', { 
     get: function() { return AuthService.token != null; } 
    }); 
}); 
<div ng-controller="LoginStatusController as ctrl"> 
    <div ng-hide="ctrl.isLoggedIn"> 

當你實際登錄並獲得令牌,你設置AuthService.token,這將是提供給所有其他服務和控制器。如果令牌變爲無效或未設置,則所有服務和控制器將失去其已認證狀態。

+0

他使用Cookie認證。 –

+0

在jwt auth scenari中,「我有一個標記」這一事實並不意味着你已經過身份驗證。通過身份驗證更像是「我的令牌有效」,必須經常檢查。 –

+0

如果令牌是隱含的,那麼只需用'true' /'false'標誌替換它即可。是的,直到你嘗試它,你纔會知道你的代幣是否有效。所以當它失敗時,將其無效。 – deceze

0

我最常做的是:

使用ui-router

  • 趁着resolve鉤(這解決了一些指定參數和其注入控制器),並定義我的路線爲主路由器的子路由器,用於檢查每個路由器上的認證變化

    scripts/services/user.js

    angular.module('yourmodule') 
        .service('userSrv', function ($http, $q) { 
        var srv = {}; 
    
        srv.getAuthenticatedUser = function() { 
         return $http.get("/authenticated_user"); 
        }; 
    
        return srv; 
        }); 
    

    腳本/路線。JS

    angular 
    .module('yourmodule') 
    .config(function ($stateProvider) { 
        $stateProvider 
        .state('authenticated', { 
         abstract: true, 
         template: '<ui-view />', 
         controller: 'AuthenticatedCtrl', 
         resolve: { 
         signedInUser: function(userSrv, $q) { 
          return userSrv.getAuthenticatedUser() 
          .then(function(null, function() { 
          //Catch any auth error, likely 403 
          //And transform it to null "signedInUser" 
          //This is the place to handle error (log, display flash) 
          return $q.resolve(null); 
          }); 
         } 
         } 
        }) 
        .state('authenticated.myspace', { 
         url: '/myspace', 
         templateUrl: 'views/myspace.html' 
        }); 
    }); 
    
  • 把你的觀點內線優勢$範圍繼承

    腳本/控制器/ authenticated.js

    angular.module('yourmodule') 
        .controller('AuthenticatedCtrl', function (signedInUser, $scope, $state) { 
        //Here you set current user to the scope 
        $scope.signedInUser= signedInUser; 
    
        $scope.logout = function() { 
        //this is where you would put your logout code. 
        //$state.go('login'); 
        }; 
    }); 
    

    的意見/ myspace.html

    <!-- here you call parent state controller $scope property --> 
    <div ng-hide="signedInUser"> 
        <h1>Login</h1> 
        With Corporate Account: <a href="/login/corporate">click here</a> 
    </div> 
    

1)我想要有實際的「is_authenticated」值。如果我只想觸發一次請求,如何才能做到這一點 我的解決方案要求經過驗證的用戶對每次路由更改。這似乎很奇怪,但這實際上是可行和快速的。查詢不應該> 30ms,這是一個非常小的選擇。儘管如此,詢問「我是否已通過身份驗證」和「獲取已通過身份驗證的用戶」是相同的事情,除了一個返回一個布爾值,另一個返回用戶。我建議,就像我剛剛指出的那樣,通過請求經過身份驗證的用戶處理「我通過身份驗證」問題,然後用「if(user)」(空值處理)對其進行佈置。

2)這個控制器是否適合擁有這個邏輯? 是的,沒有。正如你所看到的,控制器是「將用戶設置爲範圍事物」的地方,但範圍繼承允許您不必爲每條路徑重複它。雖然,http api邏輯應該被移植到一個服務上,並且路由事件(「獲取這個頁面的認證用戶,請」是一個路由事件恕我直言)應該設置在一個單獨的文件中。

注意:如果你需要完整的路線「保護」(如對未通過認證,問另外一個問題,我會很高興回答這個問題重定向)