Пользовательские права доступа к коду - PullRequest
3 голосов
/ 01 апреля 2010

У нас есть сервер, написанный на C # (Framework 3.5 SP1). Клиенты пишут клиентские приложения, используя наш серверный API. Недавно мы создали несколько уровней схем лицензирования, таких как Basic, Intermediate и All. Если у вас есть базовая лицензия, вы можете вызвать несколько методов нашего API. Точно так же, если у вас есть Intermediate, у вас есть несколько дополнительных методов для вызова, и если у вас есть All, тогда вы можете вызвать все методы.

При запуске сервера он получает тип лицензии. Теперь в каждом методе я должен проверить тип лицензии и решить, следует ли продолжить работу с функцией или вернуться.

Например, метод InterMediateMethod() может использоваться только для промежуточной лицензии и лицензии All. Так что я должен что-то вроде этого.

public void InterMediateMethod()
{
   if(licenseType == "Basic")
    {
         throw new Exception("Access denied");
    }
}

Мне кажется, это очень неудачный подход. Есть ли лучший способ сделать это? Есть ли какой-либо декларативный способ сделать это путем определения некоторых пользовательских атрибутов? Я смотрел на создание пользовательского CodeAccessSecurityAttribute, но не добился хорошего успеха.

Ответы [ 6 ]

2 голосов
/ 01 апреля 2010

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

Другая возможность может состоять в том, чтобы перепроектировать и разбить ваши API-интерфейсы на базовые / промежуточные / все «разделы» и поместить их в отдельные сборки, чтобы лицензия могла включать / отключать всю сборку, и пытаться вызвать нелицензионный Метод может просто вернуть ошибку «метод не найден» (например, исключение TypeLoadException произойдет автоматически, если вы просто не загрузили нужную сборку). Это значительно упростит тестирование и обслуживание, а также позволит избежать проверки на уровне отдельных методов.

Если вы не можете сделать это, по крайней мере, попытайтесь использовать более централизованную систему, чем оператор «если», написанный от руки в каждом методе.

Примеры (которые могут или не могут быть совместимы с вашим существующим дизайном) будут включать:

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

  • Добавьте пользовательский атрибут, чтобы пометить метод, и используйте PostSharp, чтобы добавить стандартный бит кода в метод, который будет считывать и проверять атрибут на соответствие лицензии.

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

Надеюсь, это даст вам некоторые идеи.

2 голосов
/ 01 апреля 2010

Поскольку вы добавляете логику «если» в каждый метод (и бог знает, что еще), вам может оказаться проще использовать PostSharp (AOP framework) для достижения того же самого, но лично я не нравится ни один из подходов ...

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

Мне также интересно, что другие говорят об этом.

Хороший пост, мне нравится ...

0 голосов
/ 02 апреля 2010

Я согласен с ответом @Ostati о том, что вы должны хранить 3 ветки своего кода.

Что я хотел бы дополнительно расширить, так это то, что я бы выставил 3 разные службы (предпочтительно службы WCF) и выпустил сертификаты, которые предоставляют доступ к конкретной службе. Таким образом, если кто-то попытается получить доступ к функциональности более высокого уровня, он просто не сможет получить доступ к периоду обслуживания.

0 голосов
/ 01 апреля 2010

Интересно, как люди лицензируют сервисы SOA. Они могут быть лицензированы для каждой услуги или для конечной точки.

0 голосов
/ 01 апреля 2010

Это может быть очень трудно поддерживать.
Вы можете попробовать использовать шаблон стратегии.
Это может быть вашей отправной точкой.

0 голосов
/ 01 апреля 2010

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

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

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

Компоненты для наших продуктов обычно находятся на уровне сборки, но для наших веб-продуктов они могут перейти на уровень управления сервером ASP.Net.

...