Мультитенантное приложение с несколькими экземплярами клиентов, использующими общие учетные данные


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

Итак, вот что я пытаюсь сделать:

У меня есть мультитенантное приложение с общей платформой для управления мультитенантными аспектами приложения, такими как места хранения данных и т. д. Каждый клиент будет иметь " x " число пользователей, которые могут получить доступ к данным клиента. счет. Однако каждый клиент может иметь несколько экземпляров, привязанных к его учетной записи. Например, у клиента может быть рабочий экземпляр, а также тестовый экземпляр или экземпляр dev. Каждый экземпляр имеет индивидуальное отношение к изолированной базе данных. Для меня наиболее разумно хранить учетные данные для входа на уровне платформы против информации о клиенте, а не в каждом отдельном экземпляре, поскольку это увеличит число имен пользователей и паролей экспоненциально.

Дизайн довольно прост, есть объект-арендатор, который будет иметь коллекцию пользователей и коллекцию экземпляров. Будет создан дополнительный объект перекрестной ссылки, который позволит пользователям получать доступ к определенным экземплярам. Например, я могу разрешить доступ к рабочему экземпляру только большинству пользователей-арендаторов, но для системных администраторов они будут иметь полный доступ ко всем экземплярам.

Часть, на которой я зациклился, такова:

Пользовательская информация, хранящаяся в все экземпляры должны действительно содержать только основы, такие как имя пользователя и пароль, потому что детали, такие как Имя, номер телефона и т. д. все они должны находиться в базе данных конкретного экземпляра. Что еще более важно, пользователи будут иметь отношение "один ко многим" к другой сущности в каждом случае, будь то сотрудник, человек или объект контакта.

Мой вопрос тогда становится:

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

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

Спасибо за ваш опыт!

Брент

2 2

2 ответа:

Похоже, что здесь есть три взаимосвязанные вещи, хотя вопрос вращается вокруг только одного:

  1. Как данные сохраняются в базе данных?
  2. Как обеспечить каждому пользователю доступ только к тем экземплярам, на которые у него есть права?
  3. Как вы сопоставляете данные с объектами для использования в коде?

Есть, вероятно, несколько способов решить каждый из них, но вот что я бы сделал:

Как данные хранятся в системе база данных?

Поскольку у вас есть одна база данных на клиент-экземпляр приложения (каждая "среда" - производственная, тестовая и т. д. если бы у вас были данные, относящиеся ко всем из них, я бы тоже хранил "общие" данные в отдельной базе данных.

Назовем эту базу данных базой данных SystemConfiguration. В этом случае у вас будет:

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

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

Технически вы можете разбить это на разделы другими способами, например, иметь отдельную пользовательскую базу данных и хранить только конфигурацию tenant/system в базе данных SystemConfiguration, но это, по крайней мере, дает вам идею.

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

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

Я думаю, что аутентификация/авторизация на основе утверждений значительно упростила бы эту проблему. Если вы не знакомы с утверждениями, идея заключается в том, что вместо статического списка "ролей" пользователя у вас есть словарь пар имя / значение, связанных с каждым пользователем. Словарь - это "набор утверждений" пользователя, а каждая пара имя / значение - " утверждение."Преимущество перед ролями заключается в том, что ценность может быть любой, включая список.

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

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

Возвращая его в хранилище данных-генерация набора утверждений из этой базы данных SystemConfiguration была бы тривиальным запросом.

Дополнительные сведения об идентификации на основе утверждений и использовании Windows Identity Foundation для обеспечения ее работы в приложении см. В разделе Программирование Windows Identity Foundation от Vittorio Bertocci . Это хорошая книга... и это практически единственная книга на эту тему. WIF.

Как вы сопоставляете данные с объектами для использования в коде?

На данном этапе речь идет скорее о представлении, которое вы хотите получить в данных из вашего кода, чем о структуре хранилища данных. Если вы хотите, чтобы объект Tenant имел в нем IEnumerable , это все просто футзирование с ORM по вашему выбору.

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

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

Наконец, если вам нужна информация о пользователе или клиенте в ваших экземплярах, некоторые запросы будут обращаться к базе данных SystemConfiguration, а некоторые-к базе данных экземпляра клиента. Это нормально. Пока вы используете глобально-уникальный идентификатор для всего, вы можете связать пользователь из одной базы данных в какую-то настройку или значение в другой, просто по идентификатору. Целостность ссылок немного сложнее поддерживать, но это проще, чем поддерживать синхронизацию данных между несколькими базами данных экземпляров.

Это может быть еще одной причиной, чтобы обернуть вещи в услуги. Например, если у вас есть служба" UserSettings", ваш контракт может запросить идентификатор экземпляра клиента и идентификатор пользователя и вернуть список параметров. За кулисами служба может запрашивать данные из SystemConfiguration, сопоставьте его с соответствующей базой данных экземпляра и верните объединенный набор данных-все прозрачно для вызывающего кода. С другой стороны, вы не получаете тот приятный метод "Update ()", который некоторые ORMs дают вам, когда вы просто меняете значения на объектах и хотите зафиксировать изменения. Это компромисс между тем, хотите ли вы заставить ОРМ подчиниться, чтобы это произошло.

Перепишите:

[похоже, мой первоначальный ответ был нецелевым, и это примерно то, что у вас есть. Так...]

Как я могу синхронизировать изменения или модификации данных во всех экземплярах, или я даже должен беспокоиться об этом?

Есть ли у вас требование, которое требует, чтобы вы поддерживали их синхронизацию, или любой другой драйвер? Если нет... Предполагая, что вы это сделаете, вам нужно решить, с чем вы собираетесь синхронизировать; что такое сингл источник истины.

A Publish / Subscribe или Observer Type approach может быть тем, что вам нужно.

  • экземпляры "публикуют" изменения в центральной системе, которые другие экземпляры получают либо во время их обычного жизненного цикла, либо в режиме ad-hoc на основе события / уведомления, выданного центральной системой.
  • или аналогичный, но децентрализованный подход, когда изменения транслируются всем заинтересованным сторонам сразу (гораздо сложнее, я думаю, и с новым набором проблем).