Где в стеке вызовов следует выполнять проверку ролей?

StackOverflow https://stackoverflow.com/questions/1050729

Вопрос

В моем типичном приложении пользователь нажимает кнопку на странице aspx, вызывает бизнес-объект C#, а затем запускает хранимую процедуру.

Должны ли проверки ролей выполняться наверху стека, внизу стека или на каждом уровне?Кажется, что если злонамеренный пользователь может вызвать один метод, он может вызвать любой, поэтому для эффективной безопасности вам потребуется проверка каждого метода (а это требует написания большого количества дополнительного кода).

Вот типичный стек вызовов, иллюстрирующий мой вопрос:

Page_Load()
{
  if(p.IsInRole("Managers"))  //or equivalent attribute
  {
    AddAccount.Visible =true;
  }
}

AddAccount_OnClick()
{
  if(p.IsInRole("Managers"))  //or equivalent attribute
  {
    //Add the account
    Account.Add(...);  //and maybe another role check...
  }
}

-- TSQL doesn't understand .NET authorization, this call is in a 'trusted' subsystem
create proc Add_Account @user, @account_name
If @user in (Select user from role_table where role='manager')
-- Add the account
Это было полезно?

Решение

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

Этот аргумент потребует размещения проверок безопасности либо на самом источнике данных, если он его поддерживает (например, ваша любимая СУБД), либо на уровне доступа к данным.

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

О чем-то подобном в контексте WCF я писал некоторое время назад..

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

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

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

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

Я бы поместил проверки доступа к ролям в бизнес-объекты, фактически выполняющие потенциально опасные/конфиденциальные вещи.

ИМХО, добавление проверки роли к событиям загрузки страницы и нажатия кнопок было бы излишним.Кроме того, если вы собираетесь защитить страницу, защитите ее, используя декларативные директивы местоположения в вашем web.config...напримерпоместите все ваши «админские» страницы в отдельную папку и декларативно защитите всю папку.

Но вы всегда должны, как минимум, проверять методы вашего бизнес-объекта.

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

private void MyBypassingCall()
{
  if( myLogic )
  {
    AddAccount_OnClick();
  }
}

Поэтому поместить его на Page_Load недостаточно.Вам также следует проверить украшение метода с помощью Атрибут PrincipalPermissionAttribute.Это сокращает объем кода.

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

Бизнес-объекты.

Но во время строительства.Пусть каждый экземпляр выполняет очень конкретную роль.

Редактировать:Так более лаконично.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top