Вопрос по asp.net-mvc-3 – Работа с несколькими арендаторами на MVC

1

Я хотел бы спросить ваше мнение о том, как я справляюсь с MultiTenancy. Я использую MVC3 (переключение на MVC4) и EF в качестве моего бэкэнда. Я использую одно приложение, общую схему MultiTenancy. Ниже приведен код:

public abstract class Service<T> where T : Entity
{
    private Repository<T> _repo;
    public Service()
    {
        _repo = new Repository<T>();
    }

    public bool Authenticate(int id)
    {
        //var companyInfo = _authorizationRepository.GetApiKey(apiKey);
        int tenantId = 0; // replaced by companyInfo using repository
        var entity = _repo.GetQuery(tenantId).Where(e => e.Id == id).First();

        if (tenantId != entity.TenantId)
            throw new ArgumentException();

        return true;
    }
}

public class EmployeeService : Service<Employee>
{
    private EmployeeRepository employeeRepository;
    public EmployeeService()
    {
        employeeRepository = new EmployeeRepository();
    }

    public Employee GetEmployeeById(int employeeId)
    {
        this.Authenticate(employeeId);
        return employeeRepository.GetById(employeeId);
    }
}

public class Entity
{
    public int Id { get; set; }
    public int TenantId { get; set; }
}

Конечно, я тоже буду там, но для простоты я удалил их здесь (временно). Я использовал Generics (чувствуя себя грязно из-за этого) на сервисном уровне, так как у меня возникают проблемы при сравнении TenantId с правильным Entity, который будет передан классу. Я планирую перекодировать это с помощью FilterAttributes, но не знаю, как это сделать. Как вы, ребята, справляетесь со своей арендой? Есть ли в дизайне некоторые существенные недостатки, с которыми я могу столкнуться в долгосрочной перспективе? Если у вас есть несколько примеров с использованием FilterAttributes, это было бы очень полезно.

Спасибо!

Это круто, но эта конкретная схема URL не имеет отношения к постоянному слою, который вы решите использовать. Я думаю, мне интересно, каков твой вопрос. Tejs
@ gnaungayan Если на ваш вопрос ответили, пожалуйста, отметьте его. Ty Goran Žuri
@Tejs для меня проблема в том, как я управляю маршрутизацией. Как правило, tenant1.domain.com и domain.com/tenant2 должны быть действительными и указывать на конкретного арендатора. MikeSW
@Tejs Я был обеспокоен постоянным уровнем, потому что хотел убедиться, что TenantA не будет получать / публиковать какие-либо данные из TenantB и т. Д. gnaungayan
Почему Multitenancy даже вызывает беспокойство в веб-приложении? Tejs

Ваш Ответ

1   ответ
2

б-приложение. Ну, это не так просто, как кажется, но как только вы создадите свою архитектуру, все станет проще. Наш проект находится в глубокой разработке, но вы можете проверить часть с открытым исходным кодом на сайте nanocms.codeplex.com (мы не загрузили задание для db jet в течение нескольких дней)

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

Сначала вам нужно определить арендатора для каждого запроса. У нас есть глобальный фильтр действий, который анализирует URL и сравнивает его с данными в базе данных. Конечно, вы должны кэшировать все данные, чтобы не было обращений к базе данных. Вы не должны сохранять что-либо из этого в файле cookie или сеансе, потому что пользователь может посетить более одного клиента одновременно. Я предлагаю вам поместить эти данные в элементы HttpRequest, чтобы вы делали это только один раз в запросе, но эти данные всегда были доступны всегда.

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

Я предлагаю, чтобы вы сохраняли элементы HttpRequest строго типизированными. У нас есть:

public static int TenantID {
    get { return System.Web.HttpContext.Current.Items.Contains("TenantID") ? Convert.ToInt32(System.Web.HttpContext.Current.Items["TenantID"]) : -1; }
    set {
        if (!System.Web.HttpContext.Current.Items.Contains("TenantID"))
            System.Web.HttpContext.Current.Items.Add("TenantID", value);
        System.Web.HttpContext.Current.Items["TenantID"] = value;
    }
}
Пожалуйста, объясните, обеспокоены ли вы безопасностью перекрестной публикации или просто предоставлением нужного контента нужному арендатору? В целях безопасности вы можете использовать маркер защиты от подделки, это предотвратит перекрестную почту. Для обеспечения правильного содержимого вы должны иметь tenantId в каждой родительской таблице в вашей базе данных и писать запросы соответственно.
Это больше похоже на ваше второе утверждение. Если у вас есть URL-адрес www.site.com/Employees/1 (это относится к данным TenantA), но TenantB вошел в систему и жестко запрограммировал этот URL-адрес, как мне запретить ему просматривать данные TenantA? gnaungayan
Спасибо за ответ Горан. Но как проверить, не будет ли сущность, которая будет опубликована, перейти не к тому арендатору? Например, TenantA будет вставлять / выбирать элемент, как вы гарантируете, что TenantA не будет выбирать / вставлять данные TenantB? gnaungayan
Вы никогда не должны посылать tenantID через URL. Вот почему мы анализируем входящий запрос (я имею в виду URL запроса), чтобы определить текущего клиента. Если я правильно понял ваш пример, у вас есть приложение, в котором есть сотрудники, скажем, арендаторы a и b. Вы можете иметь a.site.com/Employees и b.site.com/Employees. Разбирая URL-адрес запроса, вы получаете доступ к нескольким арендаторам, которые можно сохранить в RequestItems, как в ответе. Если вы хотите проверить права пользователя на просмотр данных, у вас может быть таблица со сложным первичным ключом userID, tenantID, roleID, и вы можете проверить, есть ли у пользователя права этого арендатора для просмотра / редактирования данных.
Кроме того, вы никогда не должны полагаться на URL или отправлять важные данные, как это. URL-адрес просто навигационный, и если вам необходимо отправить некоторые важные данные, он должен быть только для одного использования и зашифрован. Для пользователя мультитенантное приложение не должно отличаться от обычного приложения. Вы можете проверить маршрутизацию домена и получить tenantID из субдомена.

Похожие вопросы