2013-08-01 279 views
3

在我走之前,我希望有人可以告訴我,如果我正確處理這種情況,或者如果有一種更容易的方式,我只是想念。我們有一個使用AngularJS和Web API製作的網頁。我們現在正在處理用戶在嘗試訪問某些頁面時的身份驗證。我們有一個叫做權限的模塊,我們目前使用這個模塊。AngularJS身份驗證

angular.module('permissions', []).factory('permissions', function (LoginApi, $q) { 
//this is the variable which will hold the user, fetch it from the server - will return null if not authenticated 
var storedUser; 

function currentUser() { 
    var deferred = $q.defer(); 

    if (!storedUser) { 
     storedUser = LoginApi.get(function() { 
      deferred.resolve(storedUser); 
     }) 
    } 
    else { 
     deferred.resolve(storedUser); 
    } 

    return deferred.promise; 
} 

//define the permissions object that's exposed publicly 
return { 

    setUser: function (user) { 
     storedUser = user; 
    }, 
    isInRole: function (roleName) { 
     var promise = currentUser(); 
     promise.then(function() { 
      if (!storedUser || !storedUser.roles) { 
       return false; 
      } 

      //if roleName is in currentUserRoles, then return true 
      if (storedUser.roles.indexOf(roleName) > -1) { 
       return true; 
      } else { 
       return false; 
      } 
     }, function(reason) { 
      return false; 
     }); 
    }, 
    isLoggedIn: function() { 
     var promise = currentUser(); 
     promise.then(function() { 
      if (!storedUser) { 
       return false; 
      } else { 
       return true; 
      } 
     }, function(reason) { 
      return false; 
     }); 
    }, 
    firstName: function() { 
     var promise = currentUser(); 
     promise.then(function() { 
      if (!storedUser) { 
       return ''; 
      } 

      return storedUser.firstName; 
     }, function (reason) { 
      return ''; 
     }); 
    }, 
    lastName: function() { 
     var promise = currentUser(); 
     promise.then(function() { 
      if (!storedUser) { 
       return ''; 
      } 

      return storedUser.lastName; 
     }, function (reason) { 
      return ''; 
     }); 
    }, 
    email: function() { 
     var promise = currentUser(); 
     promise.then(function() { 
      if (!storedUser) { 
       return ''; 
      } 

      return storedUser.email; 
     }, function (reason) { 
      return ''; 
     }); 
    } 
}; 
}); 

正如你可以看到我使用的承諾,使我的電話等我拿到用戶如果有一個已登錄。我有這個工作,但現在我的問題是,在任何功能上我的網站處理權限,看起來我需要添加承諾和延期,因爲目前的調用並沒有等待權限函數的運行。這是正在使用的地方的一個例子是在下面

$rootScope.$on("$routeChangeStart", function (event, next, current) { 

    if (next.access == "All") 
    { 
     //do nothing 
    } 
    else if (next.access == "User") { 
     if ($rootScope.permissions.isLoggedIn()) { 
      //do nothign they have permissions required 
     } else { 
      // not going to #login, we should redirect now 
      $location.path("/login"); 
     } 
    } 
    else if (next.access == "Admin") { 
     if ($rootScope.permissions.isInRole('Admin_Base')) { 
      //do nothign they have valid permissions 
     } else { 
      // not going to #login, we should redirect now 
      $location.path("/403"); 
     } 
    } 
}); 

所以基本上,即使裏面的權限在我的職務推遲直到用戶得到返回顯示在rootScope我routeChange事件。調用這些函數的函數不會延遲,所以每次檢查權限時都會返回false。我想我可以通過向權限調用添加承諾來解決這個問題,但是我想知道是否有更簡單的方法來處理我缺少的這個問題。

回答

0

這是對不涉及承諾的更新問題的回覆。

如何使用角型曲奇緩存用戶?只要確保在註銷時清除cookie(以及任何其他正在清除服務器cookie的事件)。

您需要包含ngCookies模塊。

參見:http://docs.angularjs.org/api/ngCookies.$cookies瞭解更多詳情。

由於我沒有足夠的信譽,我無法直接對更新的問題發表評論。

+0

我最終使用cookies來完成這項工作。我不喜歡它的唯一原因是它可以讓人們能夠篡改cookie,因爲他們然後會在用戶計算機上,但是我所做的是使用cookie,直到響應返回並且那麼響應會使用來自服務器的信息設置變量 –

1

嘗試在登錄回調中廣播事件。

$rootScope.$broadcast('event:login-confirmed'); 

然後,只需將該事件用於「on」手錶即可。

$rootScope.$on("event:login-confirmed", function (event, next, current) { ... 
+0

如果我想讓它開火1次,那麼這個方法就行了,但是我每次去不同的路線時都會尋找一些東西來檢查角色。這通常不是問題,因爲一旦你登錄了,我們有你的信息,但是如果你在頁面上點擊F5,我們將失去登錄信息,我們已經存儲在前端,並且必須再次檢索它,這就是爲什麼我必須處理與承諾。 –

1

(披露:我的UserApp的開發者之一)來解決它

的一種方法是使用第三方服務UserApp,與AngularJS module在一起。

檢查出getting started guide,或採取course on Codecademy。下面是它如何工作的一些例子:

  • 登錄形式的錯誤處理:

    <form ua-login ua-error="error-msg"> 
        <input name="login" placeholder="Username"><br> 
        <input name="password" placeholder="Password" type="password"><br> 
        <button type="submit">Log in</button> 
        <p id="error-msg"></p> 
    </form> 
    
  • 註冊表格錯誤處理:

    <form ua-signup ua-error="error-msg"> 
        <input name="first_name" placeholder="Your name"><br> 
        <input name="login" ua-is-email placeholder="Email"><br> 
        <input name="password" placeholder="Password" type="password"><br> 
        <button type="submit">Create account</button> 
        <p id="error-msg"></p> 
    </form> 
    

    ua-is-email指用戶名與電子郵件相同。

  • 如何指定應該是公開的哪條路線,其路線,那就是登錄表單:

    $routeProvider.when('/login', {templateUrl: 'partials/login.html', public: true, login: true}); 
    $routeProvider.when('/signup', {templateUrl: 'partials/signup.html', public: true}); 
    

    .otherwise()路徑應設置爲您希望您的用戶登錄後重定向。例如:

    $routeProvider.otherwise({redirectTo: '/home'});

  • 註銷鏈接:

    <a href="#" ua-logout>Log Out</a>

  • Access用戶屬性:

    用戶信息是使用user服務,例如訪問:user.current.email

    或者模板:<span>{{ user.email }}</span>

  • 隱藏元素應該只看到當登錄:

    <div ng-show="user.authorized">Welcome {{ user.first_name }}!</div>

  • 顯示基於權限的元素:

    <div ua-has-permission="admin">You are an admin</div>

爲了驗證您的後端服務,只需使用user.token()獲取會話令牌並通過AJAX請求發送它。在後端,使用UserApp API來檢查令牌是否有效。

如果您需要任何幫助,只是讓我知道:)

0

您在使用的承諾和$routeChangeStart事件點是肯定的,但你仍然缺少一個或兩個關鍵部分。其中第一個是以正確的順序讓承諾發出,退回,解決並回撥到正確位置的正確模式。其基本模式是這樣的:

// 1.) Issue the promise 
var deferred = $q.defer(); 
// 2.) Initiate the asynch process 
LoginAPI.get(function(result) { 
    // Resolve the promise with the result passed into the callback 
    deferred.resolve(result); 
} 
// 3.) Return promise 
return deferred.promise; 

我通常使用UI路由器和狀態,而不是香草AngularJS路線,所以我只是要在子僞這裏,直到我得到周圍查找的實際語法。問題是,您想要中斷您的路線更改並等待承諾解決,然後重新啓動它們。

// Initialize a flag within the closure so we don't get stuck in a loop 
var pending = false 
// Catch the $routeChangeStart event 
$rootScope.$on('$routeChangeStart',function(event,next,current) { 
    // Check and flip the flag so we don't do this again when we restart 
    if (pending = !pending) { 
    // Interrupt the route change and prevent it from proceeding. 
    event.preventDefault(); 
    // Initiate auth check with callback 
    getUser().then(function(result) { 
     // if authorized 
     if (result.authd) { 
     // restart the original route change 
     // followInitialRouteTo(next); 
     } else { // if not authorized 
     // redirect to login route 
     // goTo(loginRoute); 
     } 
    } 
    } else { // second pass, pending was true 
    // do nothing and let the event be handled by angular 
    } 
}