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 ортогональны друг другу.