3

在我走远之前,我希望有人能告诉我我是否正确处理了这种情况,或者是否有一种更简单的方法我只是想念。我们有一个使用 AngularJS 和 Web API 制作的网页。我们现在正在处理用户尝试访问某些页面时的身份验证。我们有一个名为权限的模块,我们用于此当前如下所示。

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 上的 routeChange 事件中,如下所示

$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");
        }
    }
});

所以基本上即使在权限范围内,我的函数也会推迟到用户被返回。调用这些函数的函数不会延迟,因此每次检查权限时基本上都会返回 false。我想我可以通过向权限调用添加承诺来解决这个问题,但我想知道是否有一种更简单的方法来处理我缺少的这个问题。

4

4 回答 4

1

尝试在登录回调中广播事件。

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

然后只需将该事件用于您的“开启”手表。

$rootScope.$on("event:login-confirmed", function (event, next, current) { ...
于 2013-08-02T03:37:10.687 回答
1

(披露:我是UserApp的开发者之一)

解决它的一种方法是使用第三方服务UserApp以及AngularJS 模块

查看入门指南,或参加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>

  • 访问用户属性:

    使用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检查令牌是否有效。

如果您需要任何帮助,请告诉我 :)

于 2013-12-16T22:10:44.073 回答
0

这是对不涉及承诺的更新问题的回复。

使用 Angular cookie 缓存用户怎么样?只需确保在注销时清除 cookie(以及清除服务器 cookie 的任何其他事件)。

您需要包含 ngCookies 模块。

有关详细信息,请参阅:http ://docs.angularjs.org/api/ngCookies.$cookies。

由于我没有足够的声誉,我无法直接评论更新的问题。

于 2013-09-29T04:53:59.027 回答
0

你在使用 promises 和$routeChangeStartevent 方面肯定是正确的,但你仍然缺少一两个关键部分。第一个是让 Promise 以正确的顺序发出、返回、解决和回调到正确位置的正确模式。基本模式是这样的:

// 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-router 和 states 而不是 vanilla 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
  }
}
于 2014-02-15T00:06:56.823 回答