Защита конфиденциальных данных объекта - PullRequest
1 голос
/ 18 мая 2010

Я ищу совет по архитектуре для клиент-серверного решения с некоторыми особенностями.

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

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

Клиент размещает модель домена, и я подумывал о том, чтобы реализовать это как своего рода «отложенную загрузку», сделать первый запрос на создание экземпляров сущностей, а затем обновить их конфиденциальными данными. Получатели сущности будут генерировать исключения для конфиденциальной информации, когда они не были раскрыты, например: 100100

class PersonImpl : PersonEntity
{
    private bool undisclosed;

    public override string SocialSecurityNumber {
        get {
            if (undisclosed)
                throw new UndisclosedDataException();

            return base.SocialSecurityNumber;
        }
    }
}

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

get {
    if (undisclosed)
        return undisclosedValue;

    return base.SocialSecurityNumber;
}

Некоторые проблемы:

  • Что если пользователь войдет в систему и выйдет из нее, конфиденциальные данные были загружены, но должны быть раскрыты еще раз.
  • Можно утверждать, что этот тип функциональности относится к области, а не к какой-либо инфраструктурной реализации (т. Е. Реализации репозитория).
  • Как всегда при работе с большим количеством свойств, существует риск, что этот тип функциональности загромождает код

Любые идеи или обсуждения приветствуются!

Ответы [ 2 ]

2 голосов
/ 19 мая 2010

Я думаю, что это действительно хороший пример использования View Models. Похоже, ваше беспокойство напрямую связано с потреблением сущностей из-за данных, которые они содержат. Вместо того, чтобы передавать свои сущности вплоть до пользовательского интерфейса, вы можете ограничить их пребывание только в домене - т.е. никакие сущности вообще не передаются в домен или из него, при этом большинство / все действия выполняются с использованием подхода команда / запрос. на репозитории. Хранилища будут затем возвращать модель представления вместо сущности.

Так как / почему это применимо? Вы могли бы на самом деле иметь две разные модели представления. Один для аутентифицированных и один для неаутентифицированных пользователей. Вы выставляете фактические значения для конфиденциальных данных в модели аутентифицированного представления, а не для не аутентифицированной. Вы могли бы получить их из общего интерфейса, а затем кодировать интерфейс вместо типа объекта. Для вашей конкретной реализации не прошедшего проверку подлинности пользователя вы можете просто заполнить нечувствительные данные, оставив чувствительные получатели делать то, что вы хотите, чтобы они делали.

Мое мнение на пару пунктов:

  • Я не фанат ленивой загрузки сущностей. Ленивая загрузка - это ответственность за доступ к данным, а не часть модели. Для меня это первоклассный член того, чего я категорически избегаю в своей области, наряду с поиском и сортировкой. Что касается того, как связать эти элементы вместе, я бы скорее связал объекты через указатели идентификаторов с другими объектами. Если мне нужны / нужны данные, содержащиеся в одном из этих объектов, я могу загрузить их. Это своего рода ленивая загрузка в некотором смысле, но я обязуюсь, чтобы это никогда не происходило в самой модели предметной области, делая это.
  • Я не фанат создания исключений для геттеров. Сеттеры, с другой стороны, в порядке. Я смотрю на это с другой стороны. Сущность всегда должна быть в допустимом состоянии. Получатели не будут влиять на состояние объекта - установщики будут. Бросок на сеттер обеспечивает целостность модели. Использование подхода двух представлений позволило бы мне перенести логику на докладчика. Таким образом, я мог бы сделать что-то вроде «если пользователь не авторизован, сделайте это; в противном случае сделайте что-нибудь еще». Поскольку то, на что вы ссылаетесь, в конечном итоге будет представлять собой то, как данные представляются пользователю и не имеют значения для модели, я думаю, что это хорошо вписывается. В общем, я использую типы, допускающие значения NULL, для своих свойств, которые могут иметь значение NULL, и ничего не навязывать получателям, так как обычно это не входит в его обязанности. Вместо этого я использую роли, чтобы определить, какую модель представления использовать.

Очевидным недостатком является то, что для использования моделей представлений требуется больше кодирования, но оно имеет очевидное преимущество, заключающееся в разделении представлений и представлений из домена. Это также поможет в модульном / интеграционном тестировании, где вы можете проверить, что определенная модель представления не может возвращать тип данных.

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

0 голосов
/ 20 мая 2010

Я сделал ошибку, отправив вопрос без создания OpenId, поэтому мне кажется, что мне придется комментировать здесь (?).

Прежде всего, спасибо, что нашли время ответить - это, безусловно, больше связано с тем, как представлены данные, чем с тем, как работает модель. Однако я чувствую необходимость прояснить несколько вещей. На модель / сущность домена никогда не ссылаются напрямую из пользовательского интерфейса. Я использую вариант шаблона DM-V-VM для разделения UI / бизнес-модели. Для отложенной загрузки и реализации репозитория в целом у меня есть реализации сущностей на уровне инфраструктуры, где обрабатываются такие вещи, как сериализация, грязное отслеживание и отложенная загрузка.

Таким образом, у слоя домена есть такие объекты, как:

class Entity {
    virtual string SocialSecurityNumber { get; }
}

А уровень инфраструктуры добавляет некоторые другие функциональные возможности для обновления и восстановления объектов с сервера:

class EntityImpl : Entity {
    bool isDirty;
    bool isLoaded;
    // Provide the means to set value on deserialization
    override string SocialSecurityNumber;
}

Таким образом, режим отложенной загрузки будет реализован на уровне инфраструктуры и никогда не будет виден на уровне домена.

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

...