Сделайте Метод Бизнес-Слоя безопасным. лучшая практика / лучший шаблон

Мы используем ASP.NET с большим количеством Ajax "вызовы" Метода Страницы. WebServices, определенный на Странице, вызывает методы от нашего BusinessLayer. Для предотвращения хакеров для вызова Методов Страницы мы хотим реализовать некоторую безопасность в BusinessLayer.

Мы боремся с двумя другими вопросами.

Сначала один:

public List<Employees> GetAllEmployees()
{
    // do stuff
}

Этот Метод должны назвать Авторизованные пользователи с Ролью "HR".

Второй:

public Order GetMyOrder(int orderId)
{
    // do sutff
}

Этот Метод должен только назвать владелец Порядка.

Я знаю, что легко реализовать безопасность для каждого метода как:

public List<Employees> GetAllEmployees()
{
    // check if the user is in Role HR
}

или

public Order GetMyOrder(int orderId)
{
    // check if the order.Owner = user
}

То, что я ищу, является некоторым шаблоном/лучшей практикой для реализации этого вида безопасности универсальным способом (затем еще не кодируя, если каждый раз), я надеюсь, что Вы получаете то, что я имею в виду :-)

9
задан John Saunders 9 June 2010 в 17:27
поделиться

3 ответа

Пользователь @mdma немного описывает аспектно-ориентированное программирование. Для этого вам нужно будет использовать внешнюю библиотеку (например, отличный PostSharp), потому что .NET не имеет большой функциональности АОП. Однако в .NET уже есть механизм АОП для безопасности на основе ролей, который может частично решить вашу проблему. Взгляните на следующий пример стандартного кода .NET:

[PrincipalPermission(SecurityAction.Demand, Role="HR")]
public List<Employees> GetAllEmployees()
{
    // do stuff
}

Атрибут PrincipalPermissionAttribute является частью пространства имен System.Security.Permissions и является частью .NET (начиная с .NET 1.0). Я использую его уже много лет для реализации безопасности на основе ролей в своих веб-приложениях. Хорошая особенность этого атрибута заключается в том, что компилятор .NET JIT выполняет всю работу за вас в фоновом режиме, и вы даже можете определить его на уровне класса. В этом случае все члены этого типа унаследуют этот атрибут и его настройки безопасности.

Конечно, у него есть свои ограничения. Ваш второй пример кода не может быть реализован с использованием атрибута безопасности на основе ролей .NET. Я думаю, вы действительно не можете найти какие-то специальные проверки безопасности в этом методе или вызвать какую-то внутреннюю библиотеку безопасности.

public Order GetMyOrder(int orderId)
{
    Order o = GetOrderInternal(orderId);
    BusinessSecurity.ValidateOrderForCurrentUser(o);
}

Конечно, вы можете использовать структуру АОП, но вам все равно придется написать специальный атрибут инфраструктуры, который снова будет вызывать ваш собственный уровень безопасности. Это будет полезно только тогда, когда такой атрибут заменит несколько вызовов методов, например, когда нужно поместить код внутри операторов try, catch, finally.Когда вы выполняете простой вызов метода, не будет большой разницы между вызовом одного метода или одним атрибутом IMO.

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

public Order[] GetAllOrders()
{
    IQueryable orders = GetAllOrdersInternal();
    orders = BusinessSecurity.ApplySecurityOnOrders(orders);
    return orders.ToArray();
}

static class BusinessSecurity
{
    public static IQueryable<Order> ApplySecurityOnOrders(
       IQueryable<Order> orders)
    {
        var user = Membership.GetCurrentUser();

        if (user.IsInRole("Administrator"))
        {
            return orders;
        }

        return 
            from order in orders
            where order.Customer.User.Name == user.Name
            select order; 
    }
}

Когда ваш O / RM поддерживает LINQ через Деревья выражений (такие как NHibernate, LINQ to SQL и Entity Framework) вы можете написать такой метод защиты один раз и применять его везде. Конечно, хорошо то, что запрос к вашей базе данных всегда будет оптимальным. Другими словами, не будет извлечено больше записей, чем необходимо.

ОБНОВЛЕНИЕ (годы спустя):

Я долгое время использовал этот атрибут в своей базе кода, но несколько лет назад я пришел к выводу, что АОП на основе атрибутов имеет ужасные недостатки. Например, это затрудняет возможность тестирования. Поскольку защитный код сплетен с обычным кодом, вы не можете запускать обычные модульные тесты, не выдавая себя за действительного пользователя. Это непросто, и модульный тест не должен волновать его (сам модульный тест нарушает принцип единой ответственности). Кроме того, это заставляет вас засорять базу кода этим атрибутом.

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

9
ответ дан 3 November 2019 в 00:58
поделиться

Если вы используете SOA, вы можете создать Security Service, и каждое действие (метод) будет отправлять свой контекст (UserId, OrderId и т.д.). Служба безопасности знает о правилах безопасности бизнеса.

Схема может быть примерно такой

UI -> Security -> BLL -> DAL
0
ответ дан 3 November 2019 в 00:58
поделиться

Один из «лучших способов» - реализовать аспект безопасности. Благодаря этому правила безопасности отделены от основной бизнес-логики, что позволяет избежать жесткого программирования и упростить изменение правил безопасности в различных средах.

В статье ниже перечислены 7 способов реализации аспектов и разделения кода. Один из простых подходов, который не меняет интерфейс вашей бизнес-логики, - это использование прокси. Это предоставляет тот же интерфейс, что и у вас в настоящее время, но позволяет альтернативную реализацию, которая может украсить существующую реализацию. Требования безопасности можно ввести в этот интерфейс, используя жесткое кодирование или настраиваемые атрибуты. Прокси-сервер перехватывает вызовы методов вашего бизнес-уровня и вызывает соответствующие проверки безопасности. Реализация перехвата через прокси-серверы подробно описана здесь - Разделение компонентов путем внедрения настраиваемых служб в цепочку вызовов вашего объекта . Другие подходы АОП описаны в Общие сведения об АОП в .NET .

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

public static class Roles 
{
    public const string ROLE_ADMIN = "Admin";
    public const string ROLE_CONTENT_MANAGER = "Content Manager";
}

// business method    
[Security(Roles.ROLE_HR)]
public List<Employee> GetAllEmployees();

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

2
ответ дан 3 November 2019 в 00:58
поделиться
Другие вопросы по тегам:

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