Я пытаюсь понять присущий компромисс между ролями и разрешениями, когда дело доходит до контроля доступа (авторизации).
Давайте начнем с данного: в нашей системе Разрешение будет детализированной единицей доступа (« Редактировать ресурс 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+ разрешения пользователям напрямую? Какую конкретную ценность абстракции предлагают Роли (кто-то может привести конкретные примеры)?
Ответы:
На момент проверки вызывающему коду нужно только знать, «имеет ли пользователь X разрешение на выполнение действия Y?» ,
Вызывающий код не заботится и не должен знать о взаимосвязи между ролями и разрешениями.
Слой авторизации затем проверит, есть ли у пользователя это разрешение, обычно проверяя, есть ли у роли пользователя это разрешение. Это позволяет изменить логику авторизации без обновления кода вызова.
Если вы непосредственно проверяете роль на сайте вызова, вы неявно формируете отношения разрешения ролей и внедряете логику авторизации в код вызова, нарушая разделение интересов.
Если позже вы решите, что роль
foo
не должна иметь разрешенияbaz
, вам придется изменить каждый код, который проверяет, является ли пользовательfoo
.Роли концептуально представляют именованную коллекцию разрешений.
Допустим, вы добавляете новую функцию, которая позволяет пользователю редактировать определенные настройки. Эта функция должна быть доступна только администраторам.
Если вы храните разрешения для каждого пользователя, вам нужно будет найти всех пользователей в вашей базе данных, которые, как вы знаете, являются администраторами (если вы не храните информацию о ролях для пользователей, как вы узнаете, какие пользователи являются администраторами?) , И добавьте это разрешение на их список разрешений.
Если вы используете роли, вам нужно только добавить разрешение к
Administrator
роли, которое проще в исполнении, экономит место и меньше подвержено ошибкам.источник
authorization layer
скорее всего, это означает не что иное, как простое определение функции (т. Е.)user->hasPermission(SOME_PERMISSION)
Сначала внутренняя проверка ролей пользователя, а затем проверка, включает ли какая-либо из этих ролей / исключает данную разрешение. Например,the calling code
может быть проверка , чтобы увидеть , если какая - то страница отображается для пользователя и будет звонитьuser->hasPermission(VIEW_GIVEN_PAGE)
, иauthorization layer
состоит из определения вhasPermission
функции , которая проверяет роли , как указано выше.hasPermission
можно проверитьusersRole.HasPermission(VIEW_GIVEN_PAGE) && !user.Suspended
. Дело в том, что все это делается в одном месте, а не в коде потребления (вызова).В ответ на ваш первый вопрос самая большая проблема с проверкой наличия у пользователя роли, а не определенного разрешения, заключается в том, что разрешения могут поддерживаться несколькими ролями. В качестве примера этому разработчик может иметь доступ к порталу для разработчиков во внутренней сети компании, что, вероятно, также является разрешением, предоставляемым их менеджером. Если пользователь затем пытается получить доступ к порталу разработчика, у вас будет проверка, подобная следующей:
(
switch
Выражение на выбранном вами языке было бы лучше, но все же не особо аккуратно)Чем более распространено или широко распространено разрешение, тем больше ролей пользователей вам нужно будет проверить, чтобы убедиться, что кто-то может получить доступ к данной системе. Это также может привести к проблеме, заключающейся в том, что каждый раз, когда вы изменяете разрешения для роли, вам нужно будет изменить проверку, чтобы отразить это. В большой системе это стало бы очень громоздким очень быстро.
Если вы просто проверяете, что у пользователя есть разрешение, которое позволяет ему получить доступ, например, к порталу разработчика, то не имеет значения, какую роль он играет, ему будет предоставлен доступ.
Чтобы ответить на ваш второй вопрос, причина в том, что у вас есть роли, заключается в том, что они легко изменяются и распространяют «пакеты» разрешений. Если у вас есть система с сотнями ролей и тысячами разрешений, добавление нового пользователя (например, нового менеджера по персоналу) потребует от вас пройти и дать им каждое разрешение, которое есть у других менеджеров по персоналу. Это не только утомительно, но и может привести к ошибкам, если делать это вручную. Сравните это с простым добавлением роли «Менеджер отдела кадров» в профиль пользователя, который предоставит им такой же доступ, как и у любого другого пользователя с этой ролью.
Вы можете утверждать, что вы можете просто клонировать существующего пользователя (если ваша система поддерживает это), но, хотя это действительно дает пользователю правильные разрешения на тот момент времени, попытка добавить или удалить разрешение для всех пользователей в будущем может быть сложно. Примером такого сценария может быть то, что, возможно, в прошлом персонал отдела кадров также отвечал за начисление заработной платы, но в дальнейшем компания становится достаточно большой, чтобы нанимать персонал специально для обработки заработной платы. Это означает, что HR больше не нужен доступ к системе начисления заработной платы, поэтому разрешение может быть удалено. Если у вас есть 10 различных членов HR, вам нужно будет вручную пройти и убедиться, что вы удалили правильное разрешение, которое вводит возможность для ошибки пользователя. Другая проблема заключается в том, что она просто не масштабируется; По мере того, как вы получаете все больше и больше пользователей в данной роли, это значительно усложняет изменение роли. Сравните это с использованием ролей, где вам нужно всего лишь изменить общую роль, о которой идет речь, чтобы удалить разрешение, которое будет отражено каждым пользователем, которому принадлежит эта роль.
источник