Java, шаблон проектирования: менеджер по сценариям использования и актерам

В проекте у меня есть 3 актера (пользователь, эксперт, администратор) и 5 ​​основных вариантов использования (CRUD: создание, чтение, обновление, удаление и синхронизация). Но доступ пользователей к каждому варианту использования отличается от других субъектов. Например, пользователь может создать одну сущность, а эксперт и администратор могут создать произвольное число, а также другие варианты использования:

Кроме того, актеры используют один и тот же пользовательский интерфейс. Поэтому мне нужно принять решение о включении или отключении действий в отношении текущего актера во время выполнения. Кажется, это легко сделать, но мне нравится иметь хороший дизайн. Особенно, количество вариантов использования, актеры и их уровень прав доступа может измениться позже. Так что я должен соблюдать принцип OCP. Но как у меня может быть хороший дизайн для управления вариантами использования и уровнем прав доступа актеров?

1 ответ

Решение

Java поставляется с очень простой, но мощной идеей безопасности. Принципал (пользователь) обладает некоторыми разрешениями, а объект (сущность) может требовать некоторых разрешений для обработки каким-либо образом.

import java.security.Permission;
import java.security.Permissions;
import java.security.SecurityPermission;

public class PermissionFactory {
        public static Permission createOneEntity() {
            return new SecurityPermission("entity.create.one");
        }
        public static Permission createManyEntities() {
            return new SecurityPermission("entity.create.many");
        }
        public static Permission deleteEntity(Entity e) {
            return new SecurityPermission("entity.delete." + entyty.getOwnerId());
        }   

        public static Permission deleteMyEntity(User owner) {
            return new SecurityPermission("entity.delete." + user.getId());
        }   
        public static Permission deleteAnyEntity() {
            return new SecurityPermission("entity.delete.*"); // * is a placeholder for 'any'
        }   
    }

public class User {
    private final Permissions permissions  = new Permissions();

    public void addPermission(Permission p) {
        if(p != null) {
            this.permissions.add(p);
        }
    }
    public boolean hasPermission(Permission p){
        return permissions.implies(p);
    }
}

При создании пользователей вы можете хранить их разрешения вместе с ними.

User admin = new User(); 
admin.addPermission(PermissionFactory.deleteAnyEntity());
User regular = new User();
regular.addPermission(PermissionFactory.deletyMyEntitiy(tregular);

И, наконец, когда вам нужно выполнить какое-то защищенное действие, вы можете спросить основного, достаточно ли у него разрешений для этого.

Entity object = ...;
if(regular.hasPermission(PermissionFactory.deleteEntity(object)) {
delete object
}

Вы можете открыть свой интерфейс, если добавите, например, понятия "действие" и "тип сущности", а затем вместо статических методов в PermissionFactory предоставите некоторый интерфейс построителя разрешений. Но в любом случае модель безопасности и OCP ортогональны друг другу.

Другие вопросы по тегам