Quantcast
Channel: SQL.ru: Firebird, InterBase
Viewing all articles
Browse latest Browse all 1677

Вопросы о системе безопасности Firebird

$
0
0
Здравствуйте! В интернете нашел бухгалтерскую программу AZMicro2, написанную Архангельским (автор книг про Delphi), БД Firebird 2.0 и собираюсь разобраться в созданной автором системе безопасности.

https://drive.google.com/open?id=1IkPyUEmN0hD_QD33rjhFuYWNITZ9MCnY

Отривок из файла:
Система безопасности
Несмотря на то, что СУБД поддерживает таблицу пользователей, но в данном случае она не поможет......
Итак, строим таблицу Users:
Users
Таблица Users описывает как пользователей, так и их права для доступа к другим таблицам. Таким образом права устанавливает Администратор системы и пользователь может не задумываться о том с какими правами ему нужно входить. Если он вошел в систему, то она покажет ему только то, что разрешено.

Create table USERS
      (USERID       AZMID NOT NULL PRIMARY KEY,
       USERNAME     AZNAMES  NOT NULL UNIQUE, -- Login из fbsecurity.fb (ISC4.gdb)
       USRSYSNAME   AZNAMES, -- из fbsecurity.fb (ISC4.gdb)
       USRDOMAIN    AZNAMES, -- из fbsecurity.fb (ISC4.gdb)
       USRNames     AZLNAME, -- Фамилия, Имя, Отчество
       USRNPost     AZLNAME, -- Должность
/* ************************************************************************************* */
       USRGroup     CHAR(1) character set win1251, -- Текущая группа доступа
       USRLevel     AZInt32,                       -- Текущий уровень доступа
       USRRole      CHAR(2) character set Win1251, -- Допустимая группа  и 
                                                                уровень доступа
/*Блок контроля - начало*/
       DtCreate     AZTStamp,
       UsrCreate    AZMID0,                        /*references USERS on UPDATE cascade*/
       DtModify     AZTStamp,
       UsrModify    AZMID0);                       /*references USERS on UPDATE cascade*/
/*Блок контроля - конец*/
Commit;

Основные поля этой таблицы — USERID и USERNAME. Первое используется как первичный ключ и используется во всех связях, а второе уникальное имя пользователя, которое определено в БД fbsecurity.fb, и вводится пользователем в качестве Login при входе в систему.
Поля USRSYSNAME, USRDOMAIN, USRNames, USRNPost — это описательные поля, которые являются справочником для администратора.
Для определения прав доступа используются поля USRGroup, USRLevel, USRRole, которые определяются из таблицы "Система безопасности".
И, наконец, блок контроля, который имеется во всех таблицах. Для каждой строки определяются КТО и КОГДА создал запись, а также КТО и КОГДА изменил запись. Если возникнет задача репликации, т.е. перенос части этой БД в другую, то всегда можно определить новые и измененные записи.
Но кроме определения таблицы нужно заполнить ее хотя бы одной записью и наложить ограничения на структуру и другие действия.
Первая запись определяет USERID, который вводится во все таблицы по умолчанию:
Insert into Users(UserID,UserName,USRNames,USRRole)
values(0,'SYSDBA','Создатель БД','A1');
Commit;
Далее наложить ограничения, что в поля USRCreate и USRModify можно вводить только значения из самой таблицы Users.
ALTER TABLE USERS add foreign key (USRCreate) references USERS  on update cascade;
ALTER TABLE USERS add foreign key (USRModify) references USERS  on update cascade;
Commit;


Для заполнения первичного ключа нужно использовать генератор и соответствующий триггер.
CREATE GENERATOR USERS_GEN;
   SET GENERATOR USERS_GEN TO 0;
Commit;
SET TERM ^ ;
CREATE TRIGGER USERS_INSGEN FOR USERS
ACTIVE BEFORE INSERT POSITION 0
AS BEGIN
    NEW.USERID = GEN_ID(USERS_GEN,1);
END ^
SET TERM ; ^
Commit;

После всего этого нужно наложить правила, по которым можно заполнять и изменять информацию в этой таблице.
Во-первых, нужно определить какие действия являются ошибочными. В языке SQL они называются Exception (исключениями). Они не только прерывают выполнение операции, но и сообщают пользователю о его ошибке.

— нужно ограничить создание определенных ролей. Ну, не должно быть двух Директоров или Главных бухгалтеров.
— нужно запретить удаления из этой таблицы или неправомерное изменение уровня доступа.
Во-вторых, нужно создать триггеры, которые определяют эти правила:

SET TERM ^ ;
CREATE TRIGGER USERS_INSERT FOR USERS
ACTIVE BEFORE INSERT POSITION 1 AS
DECLARE VARIABLE USR SmallInt;
DECLARE VARIABLE Cnt SmallInt;
DECLARE VARIABLE Lev SmallInt;
DECLARE VARIABLE Rls Char(2) character set win1251;
BEGIN
Select USERID, USRRole,USRLevel from USERS where USERNAME=USER into :USR,:Rls,:Lev;
new.USRRole = new.USRGroup||Cast(new.USRLevel as Char(1)); 
new.UsrCreate = USR;
new.USRModify  = USR;
IF (Lev>2) then Exception NoRoleInsert;
If ((Rls='F2') and (new.USRGroup<>'F')) then Exception NoRoleInsert;
If ((Rls='T2') and (new.USRGroup<>'T')) then Exception NoRoleInsert;
If ((Rls='S2') and (new.USRGroup<>'S')) then Exception NoRoleInsert;
If ((Rls='P2') and (new.USRGroup<>'P')) then Exception NoRoleInsert;
IF (new.USRRole='A0') then begin
    Select count(*) from USERS where USRRole='A0' into :Cnt;
    If (Cnt>0) then Exception A0Exists;
    end
IF (new.USRRole='D0') then begin
    Select count(*) from USERS where USRRole='D0' into :Cnt;
    If (Cnt>0) then Exception D0Exists;
    end
IF (new.USRRole='A1') then begin
    Select count(*) from USERS where USRRole='A1' into :Cnt;
    If (Cnt>0) then Exception RoleDisable;
    end
IF (new.USRRole='F1') then begin
    Select count(*) from USERS where USRRole='F1' into :Cnt;
    If (Cnt>0) then Exception F1Exists;
    end
IF (new.USRRole='F2') then begin
    Select count(*) from USERS where USRRole='F2' into :Cnt;
    If (Cnt>0) then Exception F2Exists;
    end

    и т.д.  ..................
END ^
SET TERM ; ^
Commit;


Обяснение триггера:
Сначала определяем КТО пытается создать новую запись и какими правами он обладает и отмечаем это в полях new.UsrCreate и new.UsrModify.
Select USERID, USRRole,USRLevel from USERS where USERNAME=USER into :USR,:Rls,:Lev;
new.USRRole = new.USRGroup||Cast(new.USRLevel as Char(1));
new.UsrCreate = USR;
new.USRModify = USR;
Потом отсекаем тех, кто не может создавать записи в этой таблице — это пользователи с уровнем доступа более 2. Т.е. новые записи могут создавать только начальники подразделений.
IF (Lev>2) then Exception NoRoleInsert;
Далее определяем, что начальник подразделения может создавать записи только своего подразделения (FinDirector может создавать любые записи).
If ((Rls='F2') and (new.USRGroup<>'F')) then Exception NoRoleInsert;
И, наконец, определяем наличие ключевых должностей в таблице и если они уже есть, то вызываем исключение.


У меня возник 2 вопроса и прошу вашей помощи:
1) Если автор не использует встроенную систему безопасности сервера (в файле security3.fdb не создаёт пользователей), а создаёт свою систему безопасности тогда откуда получает в запросе внутри триггера значение переменной USER (текущий пользователь)? Тогда разве в файле безопасности не будет только суперпользователь SYSDBA?
А если использует встроенную систему безопасности сервера и создаёт там пользователей тогда как они окажутся и в таблице users?
2) Как видите в create table users в комментариях автор пишет:

 USERNAME     AZNAMES  NOT NULL UNIQUE, -- Login из fbsecurity.fb
       USRSYSNAME   AZNAMES, -- из fbsecurity.fb 
       USRDOMAIN    AZNAMES, -- из fbsecurity.fb

т.е. пока создаётся пользователь в security3.fdb и сразу в таблице users?
например так, с помощью компонента FDScript?

Begin
//вставка в security3.fdb
 if FUsersInsertEditMode=mInsert then begin
   if length(editNewPassw.text)=0 then editNewPassw.SetFocus
   else
   begin
    with Fmain.FDScript1 do begin
      SQLScripts.Clear;
      SQLScripts.Add;
      with SQLScripts[0].SQL do begin
    Add('create user '+editUserName.Text);
      end;
      ValidateAll;
      ExecuteAll;
    end;
 end;

//вставка в users
Fmain.Qusers.Open;
 if FUsersInsertEditMode=mInsert then begin
  if (EditNewPassw.Text='') then
   begin
    Application.MessageBox('Password is empty!','',MB_ICONERROR);
    exit;
   end
   else begin
    Fmain.Qusers.insert;
    Fmain.QusersUsername.AsString:=Editusername.Text;
    Fmain.Qusersuserpassw.AsString:=MD5DigestToStr(MD5String(Ansiuppercase(EditRepeatNewPassw.Text)));
    Fmain.Qusers.ApplyUpdates;
    close;
   end;
End;


Или что-то неправильно понял?

Viewing all articles
Browse latest Browse all 1677

Trending Articles