2015-07-19 1 views
2

я работаю над программой для робототехники с этой структурой (я включу, что делать слои только для смеха):Управления приватности в большой программе

  • Layer A - GUI простой интерфейс для управления кнопками, джойстиками и т. д. Переводит эти значения в команды для отправки в интерфейс управления.

  • Layer B - Контроль оценивает устройство чтения/запись-запись из запросов к базе данных и команд из графического интерфейса для того, чтобы вычислить новые устройства записи-запись для базы данных

  • слоя C - База данных логическое представление устройств, создавая историю значений, написанных и прочитанных из устройств

  • Layer D - Hardware переговоры на физическое оборудование. Переводит записи устройства-записи в команды и отправляет их на устройства. Обновляет записи устройства-устройства базы данных со значениями из устройств.

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

Возможно ли создать структуру проекта, используя конфиденциальность пакета или шаблоны, такие как фабрики, которые делают невозможным использование кода, скажем, Layer A, чтобы импортировать что-либо из слоев D или C?

ответ

2

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

Вы также не можете сделать это (каким-то образом), контролируя import ... потому что язык Java не устанавливает никаких (дополнительных) ограничений на импорт. (Директива import на самом деле является просто синтаксическим сахаром, так что вам не нужно использовать полностью квалифицированные имена повсюду.)

Так что же еще вы могли сделать?

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

  • Вы можете использовать какой-либо внутренний механизм «возможностей» или «учетных данных», но трудно понять, как предотвратить утечку учетных данных. (Если учетные данные управлялись менеджером безопасности (см ниже), которые могли бы работать, но это делает проблему более сложной.)

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

Честно говоря, реализация такого рода вещей с помощью JVM с «защитой от хакеров», вероятно, выходит за пределы возможностей смертного человека. (ВС/Oracle пока не удалось ....)


Другие альтернативы:

  • Доверьтесь дисциплины программиста.

  • Опираясь на статический анализ кода; например с помощью аннотаций, которые документируют правила доступа. Для этого вам нужно будет написать свой собственный анализатор кода.

  • Использование разделителей адресов и небольших площадей, ориентированных на безопасность API-интерфейсов между слоями. (Мы больше не говорим о единой обычной виртуальной машине Java здесь ...)

+0

Просто задал тот же вопрос Майклу Аарону Сафяну, но, на ваш взгляд, эти дорогие/привлекательные подходы реалистичны для обслуживания кода сакса? или программист дисциплины путь? – flakes

+0

Замечания программиста достаточно, если вас беспокоит только ремонтопригодность кода. ИМО. –

2

TL; DR не один волшебного решения пули, но много различных инструментов, использовать

Есть множество различных методов, чтобы изолировать различные части программного приложения, но я не думаю, что есть какое-то одно решение, которое решает все. Некоторые системы сборки могут ограничивать зависимости между целевыми объектами (например, Bazel имеет свойство visibility для целей построения, которое может помешать одной цели в зависимости от другой цели, даже если они видны друг другу через видимость класса Java), которые могут использоваться в сочетании с Java встроенный видимость. Например:

// Foo.java 
package com.yourcompany.foo; 
public class Foo {} 

// Build rule for Foo.java 
java_library(
    name = "Foo", 
    srcs = ["Foo.java"], 
    # Restricts visibility to this directory, even though 
    # the class visibility was "public" 
    visibility = ["//visibility:private"], 
) 

// Bar.java 
package com.yourcompany.bar; 

import com.yourcompany.foo.Bar; // prevented by build visibility system 

public class Bar { 
    Foo foo = new Foo(); 
} 

Кроме того, можно использовать интерфейсы, чтобы опосредовать все взаимодействия между логическими компонентами и, чтобы скрыть реализации этих интерфейсов (например, подвергая реализации только через интерфейс реестра службы или через инъекцию зависимостей интерфейса). Например, с Dagger, вы можете создать отдельный component для каждого слоя, который позволит вам написать код:

final class ControllerImpl implements Controller { 
    // Since "ControllerImpl" is instantiated/wired into the 
    // controller layer, the database dependency is available/
    // exposed for injection within this layer. The access control is 
    // strictly performed by the way the dependencies are wired. 
    @Inject 
    public ControllerImpl(Database database) { 
    // ... 
    } 
} 

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

Другим подходом является объединение различных компонентов в отдельные JAR и загрузка их с помощью настраиваемого ClassLoader, что позволит вам предотвратить незаконный доступ с использованием отражения (что в противном случае могло бы обойти любую структуру программы).

В дополнение к автоматизированным методам ручные подходы также имеют свою ценность. Ручные подходы включают регулярные проверки кода и политики, которые должны соблюдаться во время этих обзоров кода и аудита.

Короче говоря, нет ни одного правильного ответа. Необходимо использовать несколько разных подходов в зависимости от того, насколько важно это разделение.

+0

Вау, я не понимал, насколько большой вопрос на самом деле! Идея ограничения доступа к уровню заключалась в том, чтобы убедиться, что код поддерживается. Будет ли любое из этих решений целесообразным для внеурочного проекта, который, вероятно, будет длиться только год или два топа? Или, как сказал Стивен С, «Полагаться на дисциплину программиста», это более подходящий подход? – flakes

+1

Хорошо. Если речь идет только о аккуратности, а не о строгой конфиденциальности, тогда посредничество в управлении через интерфейсы, использование инфраструктуры инъекций для управления зависимостями и ручная дисциплина должно быть более чем достаточным, особенно если база кода имеет разумный/управляемый размер. Если вы еще не выбрали систему сборки, я бы порекомендовал Bazel (я немного предвзятый), и, если вы его используете, вы также можете использовать ограничения видимости. Но если у вас уже есть другая система построения, тогда такого рода вещи не нужны. –

+2

ИМО, они не были бы целесообразны для «маленького» проекта. Но если ваша цель - создать что-то, что может превратиться в жизнеспособную готовую к производству платформу с реальной безопасностью, у вас нет выбора, кроме как придумать решение для качества продукции. Не думайте, что люди еще не пробовали ... и (объективно) потерпели неудачу. Это серьезная проблема. –

 Смежные вопросы

  • Нет связанных вопросов^_^