Я б не вирішив сформулювати оригінальний коментар таким чином, як він був написаний, але він визначає потенційно законну проблему.
Зокрема, проблеми, які вимагають розділення ордера, - це автентифікація та авторизація .
Під автентифікацією розуміється процес входу та отримання ідентичності. Це те, як системи знають, хто ви є , і використовуєте їх для таких речей, як персоналізація, право власності на об'єкти тощо.
Авторизація стосується того, що вам дозволено робити , і це (як правило) не визначається тим, хто ви є . Натомість це визначається якоюсь політикою безпеки, наприклад ролями чи дозволами, які не цікавляться такими речами, як ваше ім’я чи електронна адреса.
Ці два можуть змінюватися ортогонально один до одного. Наприклад, ви можете змінити модель аутентифікації, додавши провайдерів OpenID / OpenAuth. І ви можете змінити політику безпеки, додавши нову роль або перейшовши з RBAC на ABAC.
Якщо все це відноситься до одного класу чи абстракції, то ваш код безпеки, який є одним з ваших найважливіших інструментів для зменшення ризику , стає, за іронією долі, високим ризиком.
Я працював із системами, де автентифікація та авторизація були занадто щільно поєднані. В одній системі було дві паралельні бази даних користувачів, кожна для одного типу "ролі". Людина або команда, яка розробила це, очевидно, ніколи не вважали, що один фізичний користувач може бути в обох ролях, або що можуть бути певні дії, спільні для декількох ролей, або що можуть виникнути проблеми зі зіткненнями User ID. Це, безумовно, екстремальний приклад, але працювати з цим було / неймовірно болісно.
Microsoft та Sun / Oracle (Java) називають сукупність відомостей про автентифікацію та авторизацію як про принципи безпеки . Це не ідеально, але працює досить добре. В .NET, наприклад, у вас є IPrincipal
, що інкапсулюєIIdentity
- колишнє бути політик (авторизація) об'єктом , а останній є ідентичністю (аутентифікація). Можна обґрунтовано ставити під сумнів рішення поставити один всередині іншого, але головне в тому , що велика частина коду ви пишете буде тільки для одного з абстракцій , що означає , що це легко перевірити і рефакторинг.
З User.IsAdmin
полем немає нічого поганого ... якщо тільки не існує User.Name
поля. Це вказувало б на те, що концепція "Користувач" неправильно визначена, і це, на жаль, дуже поширена помилка серед розробників, які трохи мокрі за вухами, коли мова йде про безпеку. Як правило, єдине, на що слід ділитися ідентичністю та політикою, - це ідентифікатор користувача, який, не випадково, саме те, як він реалізований і в моделях безпеки Windows, і * nix.
Цілком прийнятно створювати об’єкти обгортки, які інкапсулюють ідентичність, і політику. Наприклад, це полегшить створення екрана інформаційної панелі, де потрібно відобразити повідомлення "привіт" на додаток до різних віджетів або посилань, до яких поточний користувач може отримати доступ. Поки ця обгортка просто зафіксує інформацію про політику та інформацію про політику, і не вимагає її володіти. Іншими словами, доки він не представлений як сукупний корінь .
Спрощена модель безпеки завжди здається гарною ідеєю, коли ви вперше розробляєте нову програму через YAGNI і все це, але вона майже завжди повертається, щоб кусати вас пізніше, адже, несподіванка, сюрприз, нові функції додаються!
Отже, якщо ви знаєте, що для вас найкраще, ви зберігатимете інформацію про автентифікацію та авторизацію окремо. Навіть якщо прапор "авторизації" зараз такий же простий, як прапор "IsAdmin", вам все одно буде краще, якщо він не входить до того ж класу або таблиці, що і інформація про автентифікацію, так що якщо і коли ваша політика безпеки потребує Зміна, вам не потрібно робити реконструктивні операції на системах аутентифікації, що вже працює добре.