|
Ограничение доступа к записям
|
|||
---|---|---|---|
#18+
В базе есть некая таблица, скажем user_departments которая хранит к каким подразделением имеет доступ юзер С подразделениями связана еще тонна других таблиц например employee_departments, employee и т.п. Хочется чтобы логика доступа к подразделениям была инкапсулирована, т.е чтоб был такой объект к которому можно обратиться и получить только лишь данные к которым есть доступ у пользователя Есть вариант написать функции типа Код: plsql 1. 2. 3. 4. 5. 6. 7.
и т.д. и т.п Однако это плохо будет работать в запросах вида Код: plsql 1.
Поскольку вначале будут выбраны все сотрудники, а потом только применен фильтрующее условие в where Вот если б можно было как-то заставить предикат пропихнуться внутрь функции Вообще по специфике работы есть либо юзеры с доступом ко всем подразделениям (типа "админы") либо есть юзеры с доступом к 1-2 подразделениям. Раньше база была на оракле и для такого ограничения использовался такой кунгфу прием: Админам даем доступ на прямую к таблицам, ограниченным пользователям делаем вьюхи в которых ставим условия отсечения where userName = current_user. И для ограниченных юзеров делаем сининомы на вью с именами таблиц. Тогда подключившийся юзер (не важно "админ" это или ограниченный) просто всегда выбирает данные из обычных таблиц, а "под ка Это решение переносится на постгри и во-первых прям также сделать нельзя потому что в постгри нету синонимов,а во вторых по некоторым соображениям хочется избавиться от подключения физически под разными пользователями ... |
|||
:
Нравится:
Не нравится:
|
|||
19.01.2022, 17:37 |
|
Ограничение доступа к записям
|
|||
---|---|---|---|
#18+
Быдло__кодер, а) представления никто не отменял (имя текущего пользователя можно хранить в контексте сессии ) б) почитайте о RLS ... |
|||
:
Нравится:
Не нравится:
|
|||
19.01.2022, 22:36 |
|
Ограничение доступа к записям
|
|||
---|---|---|---|
#18+
Про RLS я читал, но меня отпугнул этот момент в доке докаTo specify which rows are visible or modifiable according to a policy, an expression is required that returns a Boolean result. This expression will be evaluated for each row prior to any conditions or functions coming from the user's query Т.е если верить этому то это еще хуже, в запросе Код: plsql 1.
cначала для каждой строчки проверится условие RLS а потом только наложится отсечение, это тогда еще печальнее чем функция Есть еще одна фигня с RLS, она не работает с foreign tables С вьюхами да, можно так сделать (и я пока не вижу других способов), но тогда "админы" (у которых в старых таблицах было фактически отсутствие записей в user_deparments) тоже будут ходить через вьюхи, т.е придется писать нечто типа такого Код: plsql 1. 2. 3. 4.
Это не особо хорошо скажется на производительности небось, особенно OR в условиях + надо будет после создания сессии устанавливать все эти параметры сесии + тогда только один юзер на сессию.. Т.е это вариант решения но с недостатками ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 01:06 |
|
Ограничение доступа к записям
|
|||
---|---|---|---|
#18+
Быдло__кодер Про RLS я читал, но меня отпугнул этот момент в доке докаTo specify which rows are visible or modifiable according to a policy, an expression is required that returns a Boolean result. This expression will be evaluated for each row prior to any conditions or functions coming from the user's query Т.е если верить этому то это еще хуже, в запросе Код: plsql 1.
cначала для каждой строчки проверится условие RLS а потом только наложится отсечение, это тогда еще печальнее чем функция Смелый вывод... вообще там дальше написано про "герметичные функции", а условие "employee_id = 123" - скорее всего будет трактоваться как "фильтр", и если по этому столбцу есть индекс, то наверняка оптимизатор это увидит. Но я не проверял, хотя проверку соорудить несложно. Вместо RLS мы решили использовать представления: у пользователей нет прямого доступа к таблицам вообще, гранты выдаются только вьюхам, а во вью уже накладываем ограничения - так тупо проще управлять всем этим хозяйством. Т.е это вариант решения но с недостатками ну, после Oracle, это меньшая из проблем, с которыми вам ещё придётся столкнуться. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 09:29 |
|
Ограничение доступа к записям
|
|||
---|---|---|---|
#18+
Быдло__кодер, аналогичную задачу решали через вьюхи. но не логическим или, а через кейсы: WHERE CASE WHEN админ THEN 1::numeric WHEN доступ разрешен THEN 1::numeric ELSE 0 END > 0::numeric; пгшный рлс очень сильно влияет на планы и заметно снижает скорость запросов во многих наших ситуациях (об этом упоминается и на стэке), поэтому от него отказались. в любом случае я бы потесткейсил оба варианта - может у вас все будет наоборот ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 11:15 |
|
Ограничение доступа к записям
|
|||
---|---|---|---|
#18+
Пощупал RLS Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56.
Под юзером user1 Код: plsql 1.
выдает Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
Судя по плану с одной стороны не так все печально, он все же не выполняет "в тупую" условие в using строчка за строчкой, а по сути выполнил select up.dep_id from user_privs up where up.user_name = current_user а потом поискал в индексе по тому что получилось. Но с другой стороны он все же не догадался вначале сделать поиск по ключу а потом проверить фильтрацию из using Остановлюсь пока на вьюхах наверное ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 23:26 |
|
Ограничение доступа к записям
|
|||
---|---|---|---|
#18+
Быдло__кодер Пощупал RLS Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56.
Под юзером user1 Код: plsql 1.
выдает Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
Судя по плану с одной стороны не так все печально, он все же не выполняет "в тупую" условие в using строчка за строчкой, а по сути выполнил select up.dep_id from user_privs up where up.user_name = current_user а потом поискал в индексе по тому что получилось. Но с другой стороны он все же не догадался вначале сделать поиск по ключу а потом проверить фильтрацию из using Остановлюсь пока на вьюхах наверное "Но с другой стороны он все же не догадался вначале сделать поиск по ключу а потом проверить фильтрацию из using " - потому что этого делать нельзя иначе выполнив запрос вида ... where (1/(employee_id-14505))>0 можно будет узнать есть такой employee_id или нет а это уже утечка данных и так по любому полю фактически. И обычные view такую утечку будут создавать всегда. А если вы сделаете view c security_barrier (boolean) This should be used if the view is intended to provide row-level security. See Section 41.5 for full details. то его поведение будет ровно тоже что у RLS https://www.postgresql.org/docs/14/sql-createview.html + https://www.postgresql.org/docs/14/rules-privileges.html там как раз разобрано как такие views ломаются. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 23:45 |
|
Ограничение доступа к записям
|
|||
---|---|---|---|
#18+
Быдло__кодер по сути выполнил select up.dep_id from user_privs up where up.user_name = current_user а потом поискал в индексе по тому что получилось. Но с другой стороны он все же не догадался вначале сделать поиск по ключу а потом проверить фильтрацию из using Ваш explain не согласен с такой трактовкой. Index Cond указан как раз именно (employee.employee_id = 14505), а подзапрос указан в Filter ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2022, 23:46 |
|
Ограничение доступа к записям
|
|||
---|---|---|---|
#18+
Ваш explain не согласен с такой трактовкой. Index Cond указан как раз именно (employee.employee_id = 14505), а подзапрос указан в Filter Хм, да, вы правы, выходит что здесь как раз он поискал по ключу а потом только наложил фильтрацию Но вот например такой запрос Код: plsql 1.
Выдает план Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
Т.е он в subPlan 1 не протолкнул таки условие на dep_id=16. В общем не все так однозначно, надо смотреть на реальных примерах будет, сложнее чем эти простые тесты - потому что этого делать нельзя иначе выполнив запрос вида ... where (1/(employee_id-14505))>0 можно будет узнать есть такой employee_id или нет а это уже утечка данных и так по любому полю фактически. И обычные view такую утечку будут создавать всегда. А если вы сделаете view c security_barrier (boolean) This should be used if the view is intended to provide row-level security. See Section 41.5 for full details. то его поведение будет ровно тоже что у RLS https://www.postgresql.org/docs/14/sql-createview.html + https://www.postgresql.org/docs/14/rules-privileges.html там как раз разобрано как такие views ломаются. Спасибо! Почитаю про это ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2022, 01:21 |
|
|
start [/forum/topic.php?fid=53&msg=40128274&tid=1993700]: |
0ms |
get settings: |
10ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
170ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
41ms |
get tp. blocked users: |
1ms |
others: | 17ms |
total: | 271ms |
0 / 0 |