Роль против контроля доступа на основе разрешений

45

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

Давайте начнем с данного: в нашей системе Разрешение будет детализированной единицей доступа (« Редактировать ресурс X », « Доступ к странице панели инструментов » и т. Д.). Роль будет набор разрешений 1+. Пользователь может иметь 1+ ролей. Все эти отношения (пользователи, роли, разрешения) все хранятся в базе данных и могут быть изменены на лету и при необходимости.

Мои опасения:

(1) Что такого плохого в проверке ролей для контроля доступа? Какие преимущества дает проверка прав доступа? Другими словами, в чем разница между этими двумя фрагментами ниже:

if(SecurityUtils.hasRole(user)) {
    // Grant them access to a feature
}

// vs.
if(SecurityUtils.hasPermission(user)) {
    // Grant them access to a feature
}

А также:

(2) В этом сценарии какую полезную ценность предоставляют даже роли? Разве мы не можем просто назначить 1+ разрешения пользователям напрямую? Какую конкретную ценность абстракции предлагают Роли (кто-то может привести конкретные примеры)?

smeeb
источник
2
Пара моментов: (1) один пользователь может иметь несколько ролей, (2) вы можете посмотреть ACL (списки контроля доступа), например. Вы можете захотеть предоставить «Доступ к странице панели мониторинга» только подмножеству страниц панели мониторинга (если их несколько).
Матье М.

Ответы:

63

(1) Что такого плохого в проверке ролей для контроля доступа? Какие преимущества дает проверка прав доступа?

На момент проверки вызывающему коду нужно только знать, «имеет ли пользователь X разрешение на выполнение действия Y?» ,
Вызывающий код не заботится и не должен знать о взаимосвязи между ролями и разрешениями.

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

Если вы непосредственно проверяете роль на сайте вызова, вы неявно формируете отношения разрешения ролей и внедряете логику авторизации в код вызова, нарушая разделение интересов.

Если позже вы решите, что роль fooне должна иметь разрешения baz, вам придется изменить каждый код, который проверяет, является ли пользователь foo.

(2) В этом сценарии какую полезную ценность предоставляют даже роли? Разве мы не можем просто назначить 1+ разрешения пользователям напрямую? Какую конкретную ценность абстракции предлагают Роли (кто-то может привести конкретные примеры)?

Роли концептуально представляют именованную коллекцию разрешений.

Допустим, вы добавляете новую функцию, которая позволяет пользователю редактировать определенные настройки. Эта функция должна быть доступна только администраторам.

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

Если вы используете роли, вам нужно только добавить разрешение к Administratorроли, которое проще в исполнении, экономит место и меньше подвержено ошибкам.

Rotem
источник
Э - э? Уровень аутентификации проверит, что пользователь - тот, кто утверждает, что является; уровень, который проверяет, к каким функциям / данным может получить доступ такой пользователь, - это уровень авторизации
SJuan76
4
Это должно быть обязательным чтением для всех программистов. Превосходно.
Коста Контос
2
Просто, кратко и по существу - где-то бьет целую главу книги. Спасибо.
Дан Ниссенбаум
2
Прокомментируйте для ясности (и, пожалуйста, исправьте меня, если я ошибаюсь): authorization layerскорее всего, это означает не что иное, как простое определение функции (т. Е.) user->hasPermission(SOME_PERMISSION)Сначала внутренняя проверка ролей пользователя, а затем проверка, включает ли какая-либо из этих ролей / исключает данную разрешение. Например, the calling codeможет быть проверка , чтобы увидеть , если какая - то страница отображается для пользователя и будет звонить user->hasPermission(VIEW_GIVEN_PAGE), и authorization layerсостоит из определения в hasPermissionфункции , которая проверяет роли , как указано выше.
Дан Ниссенбаум
1
@DanNissenbaum Да, звучит так, будто вы все правильно поняли, это может быть так же просто, как просто проверить, есть ли у роли пользователя это разрешение. Это также может быть больше, чем это. Например, может быть, у вас есть возможность временно приостановить пользователя, и в этом случае hasPermissionможно проверить usersRole.HasPermission(VIEW_GIVEN_PAGE) && !user.Suspended. Дело в том, что все это делается в одном месте, а не в коде потребления (вызова).
Rotem
18

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

if(SecurityUtils.hasRole(developer)) {
    // Grant them access to a feature
} else if(SecurityUtils.hasRole(manager)) {
    // Grant them access to a feature
} else if...

( switchВыражение на выбранном вами языке было бы лучше, но все же не особо аккуратно)

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

Если вы просто проверяете, что у пользователя есть разрешение, которое позволяет ему получить доступ, например, к порталу разработчика, то не имеет значения, какую роль он играет, ему будет предоставлен доступ.

Чтобы ответить на ваш второй вопрос, причина в том, что у вас есть роли, заключается в том, что они легко изменяются и распространяют «пакеты» разрешений. Если у вас есть система с сотнями ролей и тысячами разрешений, добавление нового пользователя (например, нового менеджера по персоналу) потребует от вас пройти и дать им каждое разрешение, которое есть у других менеджеров по персоналу. Это не только утомительно, но и может привести к ошибкам, если делать это вручную. Сравните это с простым добавлением роли «Менеджер отдела кадров» в профиль пользователя, который предоставит им такой же доступ, как и у любого другого пользователя с этой ролью.

Вы можете утверждать, что вы можете просто клонировать существующего пользователя (если ваша система поддерживает это), но, хотя это действительно дает пользователю правильные разрешения на тот момент времени, попытка добавить или удалить разрешение для всех пользователей в будущем может быть сложно. Примером такого сценария может быть то, что, возможно, в прошлом персонал отдела кадров также отвечал за начисление заработной платы, но в дальнейшем компания становится достаточно большой, чтобы нанимать персонал специально для обработки заработной платы. Это означает, что HR больше не нужен доступ к системе начисления заработной платы, поэтому разрешение может быть удалено. Если у вас есть 10 различных членов HR, вам нужно будет вручную пройти и убедиться, что вы удалили правильное разрешение, которое вводит возможность для ошибки пользователя. Другая проблема заключается в том, что она просто не масштабируется; По мере того, как вы получаете все больше и больше пользователей в данной роли, это значительно усложняет изменение роли. Сравните это с использованием ролей, где вам нужно всего лишь изменить общую роль, о которой идет речь, чтобы удалить разрешение, которое будет отражено каждым пользователем, которому принадлежит эта роль.

Мэтт Чемпион
источник
хороший пример, спасибо!
откровенно