如何设计基于angularJS资源的授权路由?

时间:2015-01-25 03:06:02

标签: javascript angularjs angular-ui-router restangular

我正在使用angularJS构建一个博客系统,现在正在尝试构建一个易于使用某些资源的资源授权流程。 例如,我有以下状态PROPOSALITEMPROPOSALITEM.VIEWPROPOSALITEM.EDITPROPOSALITEM是父状态,它通过为子状态提供的:proposalId来解析proposalItem。 PROPOSALITEM.VIEW是允许所有用户访问它的视图状态,PROPOSALITEM.EDIT是仅允许proposal owner访问的编辑页面。

我发现在本文中使用angularJS中基于role的授权流程有一个漂亮的结构:Techniques for authentication in AngularJS applications。但是我现在需要的是基于资源的所有权来决定用户是否可以访问路由。我有许多资源,例如proposal模型,需要使用所有者授权进行检查。所有这些模型都提供了owner列。有没有解决这个问题的一般解决方案? (我不想将每个模型的授权代码放在自己的解析部分中,因为它很难维护)

/* Abstract states. Resolve proposalItem */
.state('PROPOSALITEM', {
    abstract: true,
    url: '/proposals/:proposalId',
    template: '<ui-view/>',
    resolve: {
        proposalItem: function($stateParams, ProposalDataService) {
            return ProposalDataService.getItem($stateParams.proposalId);
        }
    }
})
/* View states. Allows all users to access */
.state('PROPOSALITEM.VIEW', {
    abstract: true,
    url: '/view',
    template: '...'
})
/* Edit states. Allows only the proposal owner */
.state('PROPOSALITEM.EDIT', {
    url: '/edit',
    template: '...',
    resolve: {
        proposalItem: function($q, proposalItem, UserDataService) {
            var me = UserDataService.getMe();
            // me: {
            //     _id: '1',
            //     name: '...'
            // }
            if (proposalItem.owner._id === me._id) {
                // Authorized.
                return proposalItem;
            } else {
                // Not authorized.
                var deferred = $q.defer();
                deferred.reject(ERROR_KEYS.NOT_AUTHORIZED);
                return deferred.promise;
            }
        }
    }
})

1 个答案:

答案 0 :(得分:0)

这就是我通常处理这种情况的方式。创建一个应该处理身份验证的服务:

yourapp.factory('YourResourcePermission', function () {
    return {
        check: function (resource) {
            var me = UserDataService.getMe();
            // return a promise which is resolved with the data
            // if the user has permission, or rejected otherwise.
        }
    };
});

然后,您将此服务用作所需状态的解析参数:

.state('PROPOSALITEM.EDIT', {
url: '/edit',
template: '...',
resolve: function (proposalItem, YourResourcePermission) {  
    return YourResourcePermission.check(proposalItem);
}

})

通过这种方式,您可以将所有权限逻辑与专用(和可重用)服务中的路由保持一致。

如果您有几个州需要相同的需求样板,您可以使用Angular $ provide.decorator自动将自定义逻辑注入您的状态。 请参阅:https://github.com/christopherthielen/ui-router-extras/blob/master/src/dsr.js#L10和此https://stackoverflow.com/a/26848546/3794660作为参考,了解如何装饰$ stateProvider并创建基本上具有“解决方案”的自定义状态类型。 param已经确定。

希望这有用。