Шаблоны авторизации службы WCF

Я реализую безопасную службу WCF. Аутентификация выполняется с использованием имени пользователя / пароля или учетных данных Windows. Служба размещается в процессе службы Windows. Теперь я пытаюсь найти лучший способ реализовать разрешение для каждой операции службы.

Например, рассмотрим следующий метод:

public EntityInfo GetEntityInfo(string entityId);

Как вы, возможно, знаете, в WCF есть объект OperationContext, из которого вы можете получить учетные данные безопасности, переданные вызывающим / клиентом. Теперь аутентификация уже будет завершен к тому времени, когда будет вызвана первая строка в методе. Однако как реализовать авторизацию, если решение зависит от самих входных данных? Например, в приведенном выше случае, скажем, пользователям с правами администратора (чьи разрешения и т. д. Хранятся в базе данных) разрешено получать информацию об объектах, а другим пользователям не должно быть разрешено ... где мы помещаем проверки авторизации?

Скажем, мы поместили его в первую строку метода следующим образом:

CheckAccessPermission(PermissionType.GetEntity, user, entityId) //user is pulled from the current OperationContext

Теперь есть пара вопросов:

  1. Проверяем ли мы entityId (например, проверяем нулевое / пустое значение и т. д.) ПЕРЕД проверкой авторизации или ВНУТРИ проверки авторизации? Другими словами, если проверки авторизации должны быть включены в каждый метод, будет ли это хорошим шаблоном? Что должно произойти первым - проверка аргумента или авторизация?

  2. Как мы проводим модульное тестирование службы WCF, когда проверки авторизации происходят повсюду, как это, и у нас нет OperationContext в модульном тесте !? (Предполагая, что я пытаюсь протестировать эту реализацию класса обслуживания напрямую, без какой-либо настройки WCF).

Есть идеи, ребята?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
0
10 771
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Кстати, вместо использования собственного метода проверки подлинности (который, как я предполагаю, является вашим CheckAccessPermission), вы можете подключиться к готовой поддержке WCF для поставщиков ролей ASP.NET. Как только это будет сделано, вы выполните авторизацию через OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.IsInRole (). PrimaryIdentity - это IPrincipal.

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

Krishna 28.09.2008 07:52

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

Paul Lalonde 02.10.2008 15:01

Нет. Допустим, я хочу получить доступ к объекту с идентификатором 'abc1'. Я user1. Авторизация определяет, может ли «пользователь 1» получить доступ к объекту «abc1». поэтому первое, что нужно сделать, это проверить параметр, содержащий строку идентификатора объекта!

Krishna 12.10.2008 04:25
Ответ принят как подходящий

Для вопроса 1 обязательно сначала авторизуйтесь. Никакой код (под вашим контролем) не должен выполняться до авторизации для обеспечения максимальной безопасности. Приведенный выше пример Павла превосходен.

Что касается вопроса 2, вы можете справиться с этим, создав подкласс своей конкретной реализации службы. Сделайте настоящую реализацию бизнес-логики абстрактным классом с помощью абстрактного метода CheckPermissions, как вы упомянули выше. Затем создайте 2 подкласса, один для использования WCF и один (очень изолированный в неразвернутой DLL), который возвращает true (или все, что вы хотите сделать в своем модульном тестировании).

Пример (обратите внимание, они не должны находиться в одном файле или даже в DLL!):

public abstract class MyServiceImpl
{
    public void MyMethod(string entityId)
    {
        CheckPermissions(entityId);
        //move along...
    }
    protected abstract bool CheckPermissions(string entityId);
}

public class MyServiceUnitTest
{
    private bool CheckPermissions(string entityId)
    {
        return true;
    }
}

public class MyServiceMyAuth
{
    private bool CheckPermissions(string entityId)
    {
        //do some custom authentication
        return true;
    }
}

Затем ваше развертывание WCF использует класс «MyServiceMyAuth», и вы проводите модульное тестирование против другого.

Что касается вопроса №2, я бы сделал это с помощью внедрения зависимостей и настроил бы вашу реализацию службы примерно так:

class MyService : IMyService
{
    public MyService() : this(new UserAuthorization()) { }
    public MyService(IAuthorization auth) { _auth = auth; }

    private IAuthorization _auth;

    public EntityInfo GetEntityInfo(string entityId)
    {
            _auth.CheckAccessPermission(PermissionType.GetEntity, 
                    user, entityId);

            //Get the entity info
    }
}

Обратите внимание, что IAuthorization - это интерфейс, который вы должны определить.

Поскольку вы собираетесь тестировать тип службы напрямую (то есть без запуска ее внутри инфраструктуры хостинга WCF), вы просто настраиваете свою службу на использование фиктивного типа IAuthorization, который разрешает все вызовы. Однако еще ЛУЧШИЙ тест - это имитировать авторизацию IA и проверить, что она вызывается, когда и с параметрами, которые вы ожидаете. Это позволяет вам проверить правильность ваших вызовов методов авторизации вместе с самим методом.

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

Я предпочитаю фреймворк для фиксации RhinoMocks, он бесплатный и имеет очень приятный свободный интерфейс, но есть и другие. Если вы хотите узнать больше о DI, вот несколько хороших примеров и фреймворков .Net:

Другие вопросы по теме