Каким образом можно скрыть/показать AngularJS или любое другое приложение с одной страницей приложений на основе прав аутентифицированных пользователей?

У меня есть приложение, которое использует Spring Безопасность для аутентификации/авторизации на стороне сервера, Spring MVC для конечных точек сервера сервера REST и AngularJS для просмотра.

На стороне сервера я реализовал все фильтры, необходимые для доступа ко всем этим конечным точкам REST, на основе прав пользователя. Мой вопрос: как мне подойти к созданию видимых/скрывающих элементов html на основе прав аутентифицированных USER?

Например, у меня есть в представлении 3 кнопки (кнопка1, кнопка2, кнопка3). Каждая кнопка имеет соответствующий USER RIGHT, который должен сделать их видимыми/скрытыми. Позвольте называть это прав USER_RIGHT1, USER_RIGHT2, USER_RIGHT3.

Если пользователь имеет право USER_RIGHT1, он должен видеть в представлении кнопку 1, если у него есть правильный USER_RIGHT2, он должен видеть в представлении кнопку2 и т.д.

Мой подход состоял в том, чтобы иметь список аутентифицированных прав пользователя в клиенте и сделать что-то в следующем примере:

<div ng-if="rights contains USER_RIGHT1">
    <button name="button1".... />
</div>
<div ng-if="rights contains USER_RIGHT2">
    <button name="button2".... />
</div>

Я не уверен, должен ли список прав аутентифицированного пользователя быть в клиенте.

Как мне подойти к этой проблеме? Правильно ли я делаю это?

Ответ 1

Безопасность на клиенте, то есть в браузере, находится рядом с бесполезным. Тем не менее, он должен присутствовать, чтобы не дать среднему пользователю увидеть что-то, что им не нужно, однако сервер должен быть гарантией конечного места.

Я бы создал быструю директиву для создания компонентов отображения/скрытия или пользовательского интерфейса и иметь службу проверки подлинности для выполнения фактической логики, чтобы определить, имеет ли пользователь правильные права.

Я фактическ около 60% пути написания углубленной статьи об авторизации в AngularJS в своем блоге. Я вернусь примерно через неделю, и я должен сделать это - это может помочь вам с авторизацией маршрута.

UPDATE: сообщение в блоге о angular авторизации и безопасности маршрута можно найти здесь

В основном служба авторизации авторизует пользователя с вашей бэкэнд-службой, а затем сохраняет права на их приложения.

Затем эта директива будет использовать эту службу, чтобы определить, имеет ли пользователь достаточные права на просмотр компонента пользовательского интерфейса.

Я не тестировал приведенный ниже код, поэтому вам может понадобиться его отладить.

    angular.module('myApp').factory('authService', [
    function () {
        var loggedInUser,
            login = function (email, password) {
                //call server and rights are returned
                //loggedInUser is assigned
            },
            hasSecurityRoles = function (requiredRoles) {
                var hasRole = false,
                    roleCheckPassed = false,
                    loweredRoles;
                if (loggedInUser === undefined) {
                    hasRole = false;
                } else if (loggedInUser !== undefined && requiredRoles === undefined) {
                    hasRole = true;
                } else if (loggedInUser !== undefined && requiredRoles !== undefined) {
                    if (requiredRoles.length === 0) {
                        hasRole = true;
                    } else if (loggedInUser.permittedActions === undefined) {
                        hasRole = false;
                    } else {
                        loweredRoles = [];
                        angular.forEach(loggedInUser.permittedActions, function (role) {
                            loweredRoles.push(role.name.toLowerCase());
                        });

                        // check user has at least one role in given required roles
                        angular.forEach(requiredRoles, function (role) {
                            roleCheckPassed = roleCheckPassed || _.contains(loweredRoles, role.toLowerCase());
                        });

                        hasRole = roleCheckPassed;
                    }
                }

                return hasRole;
            };

        return {
            login: login,
            hasSecurityRoles: hasSecurityRoles
        };
    }
]);

    angular.module('myApp').directive('visibleToRoles', [
        'authService',
        function (authService) {
            return {
                link: function (scope, element, attrs) {
                    var makeVisible = function () {
                            element.removeClass('hidden');
                        },
                        makeHidden = function () {
                            element.addClass('hidden');
                        },
                        determineVisibility = function (resetFirst) {
                            if (resetFirst) {
                                makeVisible();
                            }

                            if (authService.hasSecurityRoles(roles)) {
                                makeVisible();
                            } else {
                                makeHidden();
                            }
                        },
                        roles = attrs.visibleToRoles.split(',');


                    if (roles.length > 0) {
                        determineVisibility(true);
                    }
                }
            };
        }
    ]);

Затем вы использовали бы это как

<div visible-to-role="admin,usermanager">.....</div>

Ответ 2

Мой подход - это в основном то, что вы предлагаете.

У вас может быть factory, который хранит массив разрешений пользователя и имеет функцию проверки наличия разрешения в массиве:

.factory('Auth', function() {

var permissions = [];

return {
    allowed : function(permission) {

        return _.contains(permissions, permission);
    }
};});

Тогда вы можете иметь директиву, которая показывает/скрывает элемент, используя службу:

.directive('allowed', function(Auth){

    return {

        link : function(scope, elem, attr) {

            if(!Auth.allowed(attr.allowed)){
                elem.hide();
            }
        }
    };
});

Итак, в ваших взглядах вам нужно только сделать:

<div allowed="permission_name"> </div>

Ответ 3

Вместо того, чтобы иметь жестко закодированный список в ваших шаблонах/страницах, вы можете получить список прав аутентифицированных пользователей с сервера и загрузить его в свою область действия, а затем сделать то же самое, что и вы. Если вы используете ui-router, это возможно с помощью свойства разрешения (которое предварительно загружает определенные данные, возможно, с сервера до вызова контроллера).

Таким образом вы можете получать права только для пользователя, который смотрит на страницу, а не на все права, жестко закодированные на клиенте.