Дескриптор безопасности

Материал из GedeminWiki
(Различия между версиями)
Перейти к: навигация, поиск
 
(Проверка на вхождение текущего пользователя в указанную группу)
 
(не показаны 8 промежуточных версий 1 участника)
Строка 1: Строка 1:
Дескриптор безопасности -- это 32-х битовое целое число содержащее битовую маску групп пользователей обладающих определенным правом доступа. Если n-ый бит в дескрипторе установлен, следовательно группа пользователей с id=n обладает указанным правом.  
+
Дескриптор безопасности — это 32-х битовое целое число содержащее битовую маску групп пользователей обладающих определенным правом доступа. Если n-ый бит в дескрипторе установлен, следовательно группа пользователей с id=n обладает указанным правом.  
  
 
== Разграничение доступа на уровне записи ==
 
== Разграничение доступа на уровне записи ==
  
Одно из применений дескриптора безопасности -- это разграничение доступа к отдельным записям в таблице. Для этого в таблицу добавляются от одного до трех полей имеющих предопределенные названия: AVIEW, ACHAG, AFULL. Тип полей задается доменом dsecurity.
+
Основное применение дескриптора безопасности — это разграничение доступа к записям в таблице. Для этого в таблицу добавляются от одного до трех полей имеющих предопределенные названия: '''AVIEW''', '''ACHAG''', '''AFULL'''. Тип полей задается доменом [[dsecurity]].
 
+
Поле AVIEW определяет какие группы имеют право на просмотр записи, ACHAG определяет множество групп имеющие право на изменение записи и, наконец, AFULL -- дескриптор безопасности полного доступа к записи (просмотр, изменение, удаление, печать, изменение прав доступа).
+
  
 +
Поле '''AVIEW''' определяет какие группы имеют право на просмотр записи, '''ACHAG''' определяет множество групп имеющие право на изменение записи и, наконец, '''AFULL''' &mdash дескриптор безопасности полного доступа к записи (просмотр, изменение, удаление, печать, изменение прав доступа).
  
 
== Набор групп текущего пользователя ==
 
== Набор групп текущего пользователя ==
  
Множество групп, в которые входит текущий пользователь, задается битовой маской, хранящейся в свойстве
+
Множество групп, в которые входит текущий пользователь, задается битовой маской, хранящейся в свойстве '''InGroup''' глобального объекта '''IBLogin'''.
InGroup глобального объекта IBLogin.
+
  
 
Ниде приводится пример кода, который позволяет получить строку с наименованиями всех групп, в которые входит текущий пользователь системы:
 
Ниде приводится пример кода, который позволяет получить строку с наименованиями всех групп, в которые входит текущий пользователь системы:
  
<pre>
+
<syntaxhighlight lang="vbnet">
 
+
  ...
...
+
 
   dim Creator, UG, InGroups
 
   dim Creator, UG, InGroups
 
   set Creator = new TCreator
 
   set Creator = new TCreator
Строка 24: Строка 21:
 
   UG.Open
 
   UG.Open
 
   do while not UG.EOF
 
   do while not UG.EOF
     if ((2 ^ (UG.id - 1)) and IBLogin.InGroup) <> 0 then
+
     if ((UG.id = 32) and (CLng(IBLogin.InGroup) < 0)) _
 +
      or (((2 ^ (UG.id - 1)) and IBLogin.InGroup) <> 0) then
 
       if InGroups > "" then
 
       if InGroups > "" then
 
         InGroups = InGroups & ", "
 
         InGroups = InGroups & ", "
Строка 32: Строка 30:
 
     UG.Next
 
     UG.Next
 
   loop
 
   loop
...
+
  ...
 +
</syntaxhighlight>
 +
 
 +
Аналогичного результата можно добиться с помощью SQL запроса. Запрос ниже выводит список пользователей и групп для каждого пользователя:
 +
 
 +
<syntaxhighlight lang="SQL">
 +
SELECT
 +
  u.name,
 +
  LIST(g.name, ', ')
 +
FROM
 +
  gd_user u JOIN gd_usergroup g
 +
    ON BIN_AND(u.ingroup, BIN_SHL(1, g.id - 1)) <> 0
 +
GROUP BY
 +
  u.name
 +
</syntaxhighlight>
 +
 
 +
Следующий запрос выведет список групп для заданного пользователя:
 +
 
 +
<syntaxhighlight lang="SQL">
 +
SELECT
 +
  ug.id, ug.name
 +
FROM
 +
  gd_usergroup ug JOIN gd_user u ON BIN_AND(u.ingorup, BIN_SHL(1, ug.id - 1)) <> 0
 +
WHERE
 +
  u.id = :UserKey
 +
</syntaxhighlight>
 +
 
 +
== Проверка на вхождение текущего пользователя в указанную группу ==
 +
 
 +
ID группы задается через переменную '''UserGroupID'''. Результат -- в булевской переменной '''Flag'''.
 +
 
 +
<syntaxhighlight lang="vbnet">
 +
Dim UserGroupID, UserInGroup, Flag
 +
 
 +
UserGroupID = ...
 +
UserInGroup = CLng(IBLogin.InGroup)
 +
 
 +
If (UserInGroup < 0) And (UserGroupID = 32) Then
 +
  Flag = True
 +
Else
 +
  Flag = (UserInGroup AND CLng(2 ^ (UserGroupID - 1))) <> 0
 +
End If
 +
</syntaxhighlight>
 +
 
 +
Обратите внимание, что для группы с ИД = 32 возведение в степень даст результат, выходящий за диапазон типа Lng. Такой случай мы обрабатываем отдельно. Подробнее см. [http://code.google.com/p/gedemin/issues/detail?id=3326 Issue3326]
 +
 
 +
Следующий запрос поможет найти всех пользователей, входящих в заданную группу:
 +
 
 +
<syntaxhighlight lang="SQL">
 +
SELECT
 +
  u.*
 +
FROM
 +
  GD_USERGROUP gr
 +
    LEFT JOIN GD_USER u ON
 +
      BIN_AND(BIN_SHL(1, (gr.ID - 1)), u.INGROUP) <> 0
 +
WHERE
 +
  gr.iD = :GroupKey
 +
</syntaxhighlight>
 +
 
 +
== Очистка заданного бита в дескрипторах безопасности ==
 +
 
 +
При создании новой группы соответствующий бит в дескрипторах безопасности существующих записей уже может быть установлен. Соответственно, группа получит доступ к таким записям. Приведенный ниже запрос снимает бит для групп с илентификатором, заданным параметром N, для всех шапок документов:
 +
 
 +
<syntaxhighlight lang="SQL">
 +
UPDATE gd_document SET aview=bin_and(aview, bin_not(bin_shl(1, :n-1))),
 +
  achag=bin_and(achag, bin_not(bin_shl(1, :n-1))),
 +
  afull=bin_and(afull, bin_not(bin_shl(1, :n-1)))
 +
WHERE
 +
  parent IS NULL
 +
</syntaxhighlight>
 +
 
 +
== Установка заданного бита в дескрипторах безопасности ==
 +
 
 +
Приведенный ниже запрос устанавливает бит для групп с илентификатором, заданным параметром N, для всех шапок документов:
 +
 
 +
<syntaxhighlight lang="SQL">
 +
UPDATE gd_document SET aview=bin_or(aview, bin_shl(1, :n-1)),
 +
  achag=bin_or(achag, bin_shl(1, :n-1)),
 +
  afull=bin_or(afull, bin_shl(1, :n-1))
 +
WHERE
 +
  parent IS NULL
 +
</syntaxhighlight>
  
</pre>
+
[[Category:База данных]]
 +
[[Category:Руководство разработчика]]
 +
[[Category:Безопасность]]
 +
__NOTOC__

Текущая версия на 13:45, 18 апреля 2022

Дескриптор безопасности — это 32-х битовое целое число содержащее битовую маску групп пользователей обладающих определенным правом доступа. Если n-ый бит в дескрипторе установлен, следовательно группа пользователей с id=n обладает указанным правом.

[править] Разграничение доступа на уровне записи

Основное применение дескриптора безопасности — это разграничение доступа к записям в таблице. Для этого в таблицу добавляются от одного до трех полей имеющих предопределенные названия: AVIEW, ACHAG, AFULL. Тип полей задается доменом dsecurity.

Поле AVIEW определяет какие группы имеют право на просмотр записи, ACHAG определяет множество групп имеющие право на изменение записи и, наконец, AFULL &mdash дескриптор безопасности полного доступа к записи (просмотр, изменение, удаление, печать, изменение прав доступа).

[править] Набор групп текущего пользователя

Множество групп, в которые входит текущий пользователь, задается битовой маской, хранящейся в свойстве InGroup глобального объекта IBLogin.

Ниде приводится пример кода, который позволяет получить строку с наименованиями всех групп, в которые входит текущий пользователь системы:

  ...
  dim Creator, UG, InGroups
  set Creator = new TCreator
  set UG = Creator.GetObject(Application, "TgdcUserGroup", "")
  InGroups = "" 
  UG.Open
  do while not UG.EOF
    if ((UG.id = 32) and (CLng(IBLogin.InGroup) < 0)) _
       or (((2 ^ (UG.id - 1)) and IBLogin.InGroup) <> 0) then
      if InGroups > "" then
        InGroups = InGroups & ", "
      end if
      InGroups = InGroups & UG.FieldByName("name").AsString
    end if
    UG.Next
  loop
  ...

Аналогичного результата можно добиться с помощью SQL запроса. Запрос ниже выводит список пользователей и групп для каждого пользователя:

SELECT
  u.name,
  LIST(g.name, ', ')
FROM
  gd_user u JOIN gd_usergroup g
    ON BIN_AND(u.ingroup, BIN_SHL(1, g.id - 1)) <> 0
GROUP BY
  u.name

Следующий запрос выведет список групп для заданного пользователя:

SELECT
  ug.id, ug.name
FROM
  gd_usergroup ug JOIN gd_user u ON BIN_AND(u.ingorup, BIN_SHL(1, ug.id - 1)) <> 0
WHERE
  u.id = :UserKey

[править] Проверка на вхождение текущего пользователя в указанную группу

ID группы задается через переменную UserGroupID. Результат -- в булевской переменной Flag.

Dim UserGroupID, UserInGroup, Flag
 
UserGroupID = ...
UserInGroup = CLng(IBLogin.InGroup)
 
If (UserInGroup < 0) And (UserGroupID = 32) Then
  Flag = True
Else
  Flag = (UserInGroup AND CLng(2 ^ (UserGroupID - 1))) <> 0
End If

Обратите внимание, что для группы с ИД = 32 возведение в степень даст результат, выходящий за диапазон типа Lng. Такой случай мы обрабатываем отдельно. Подробнее см. Issue3326

Следующий запрос поможет найти всех пользователей, входящих в заданную группу:

SELECT 
  u.*
FROM 
  GD_USERGROUP gr
    LEFT JOIN GD_USER u ON
      BIN_AND(BIN_SHL(1, (gr.ID - 1)), u.INGROUP) <> 0
WHERE 
  gr.iD = :GroupKey

[править] Очистка заданного бита в дескрипторах безопасности

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

UPDATE gd_document SET aview=bin_and(aview, bin_not(bin_shl(1, :n-1))),
  achag=bin_and(achag, bin_not(bin_shl(1, :n-1))),
  afull=bin_and(afull, bin_not(bin_shl(1, :n-1)))
WHERE
  parent IS NULL

[править] Установка заданного бита в дескрипторах безопасности

Приведенный ниже запрос устанавливает бит для групп с илентификатором, заданным параметром N, для всех шапок документов:

UPDATE gd_document SET aview=bin_or(aview, bin_shl(1, :n-1)),
  achag=bin_or(achag, bin_shl(1, :n-1)),
  afull=bin_or(afull, bin_shl(1, :n-1))
WHERE
  parent IS NULL
Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
Инструменты