Роль проти дозволу на основі контролю доступу


44

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

Почнемо із заданого: у нашій системі Permission буде дрібнозернистим блоком доступу (" Редагувати ресурс 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+ дозволів безпосередньо? Яке конкретне значення абстракції пропонують Ролі (може хтось наводити конкретні приклади)?


2
Кілька пунктів: (1) у одного користувача може бути кілька ролей; (2) ви можете заглянути в списки ACL (списки контролю доступу), наприклад. можливо, ви зможете надати "Доступ до сторінки інформаційної панелі" лише підмножині сторінок інформаційної панелі (якщо їх декілька).
Матьє М.

Відповіді:


62

(1) Що таке "погано" у перевірці Ролей на контроль доступу? Які переваги ви отримуєте, перевіряючи натомість дозволи на отримання дозволів?

На момент перевірки викликовим кодом потрібно лише знати, "чи має користувач X дозвіл на виконання дії Y?" .
Код виклику не хвилює і не повинен знати про зв’язки між ролями та дозволами.

Після цього рівень авторизації перевірятиме, чи має користувач цей дозвіл, як правило, перевіряючи, чи має цей дозвіл роль ролі користувача. Це дозволяє змінити логіку авторизації без оновлення коду виклику.

Якщо ви безпосередньо перевіряєте роль на сайті виклику, ви неявно формуєте відносини дозволів ролі та вводите логіку авторизації в код виклику, порушуючи розділення проблем.

Якщо згодом ви вирішите, що на роль fooне повинно бути дозволу baz, вам доведеться змінити кожен код, який перевіряє, чи є користувач foo.

(2) Яке корисне значення у цьому сценарії надають Ролі? Чи не можемо ми просто призначити користувачам 1+ дозволів безпосередньо? Яке конкретне значення абстракції пропонують Ролі (може хтось наводити конкретні приклади)?

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

Скажімо, ви додаєте нову функцію, яка дозволяє користувачеві редагувати певні налаштування. Ця функція повинна бути доступна лише адміністраторам.

Якщо ви зберігаєте дозволи на одного користувача, вам доведеться знайти всіх користувачів у вашій базі даних, які ви якось знаєте, є адміністраторами (якщо ви не зберігаєте інформацію про ролі для користувачів, як би ви навіть знали, які користувачі є адміністраторами?) Та додавати це дозвіл на їх перелік дозволів.

Якщо ви використовуєте ролі, вам потрібно лише додати дозвіл на Administratorроль, яка є і простішою у виконанні, і просторішою, і менш схильною до помилок.


А? Шлях аутентифікації перевірить, що користувач саме той, хто претендує на таке; шаром, який перевіряє, до яких функцій / даних може отримати доступ такий користувач, є рівень авторизації
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. Сенс у тому, що це все робиться в одному місці, а не в споживчому (дзвінку) коді.
Ротем

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, вам потрібно буде вручну пройти і переконайтесь, що ви видалили правильний дозвіл, який вводить можливість помилки користувача. Інша проблема з цим полягає в тому, що він просто не масштабується; оскільки ви отримуєте все більше і більше користувачів у певній ролі, це ускладнює модифікацію ролі. Порівняйте це з використанням ролей, коли вам потрібно буде лише змінити загальну роль, про яку йдеться, щоб видалити дозвіл, що відображатиметься кожним користувачем, який виконує цю роль.


хороший приклад, дякую!
відвертий
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.