Авторизация на Delphi

Авторизация Delphi

Авторизация на Delphi — это одна из интереснейшим тем программирования. Что вообще представляет из себя процесс авторизации?

Авторизация пользователя — это процесс подтверждения его личности для предоставления доступа к определенным ресурсам или функциям. В настоящее время существует множество методов авторизации, каждый из которых имеет свои преимущества и недостатки.

Виды авторизации пользователей

Можно выделить основные существующие способы авторизации пользователей в программах:

  1. Логин и пароль — классический метод авторизации, который используется во многих сервисах. Он прост в использовании и обеспечивает высокую степень безопасности, если пароли хранятся правильно. Однако, многие пользователи испытывают сложности с запоминанием паролей и предпочитают использовать альтернативные методы.
  2. Двухфакторная авторизация — это метод, при котором пользователь должен ввести не только логин и пароль, но и дополнительный код, полученный на телефон или электронную почту. Этот метод обеспечивает более высокий уровень безопасности, так как даже если злоумышленник узнает пароль пользователя, без доступа к дополнительному коду он не сможет войти в аккаунт.
  3. Биометрическая авторизация — использование отпечатков пальцев, сетчатки глаза или голоса для идентификации пользователя. Этот метод быстрый и удобный, однако он может быть менее безопасным, особенно если биометрические данные хранятся на сервере в незашифрованном виде.
  4. OAuth 2.

В этом посте мы рассмотрим классический метод авторизации пользователей. Очевидно, что для создания формы авторизации пользователя следует воспользоваться обычной формой.

Форма авторизации пользователя

В основном все приложения создаются по одному из двух типов: многодокументное (MDI) и однодокументное (SDI). Создание формы авторизации и ее взаимодействие с программой мы рассмотрим на примере многодокументного типа приложения. Авторизация пользователя в однодокументном приложении происходит совершенно аналогично.

Создать форму авторизации можно двумя способами. Можно сделать так, что она будет появляться в самом начале перед загрузкой главной формы приложения:

Окно авторизации в Delphi
Окно авторизации вне главного окна приложения

А можно сделать так, что окно авторизации (форма) будет загружено как модальное вместе с главной формой приложения:

Окно авторизации программы
Окно авторизации программы внутри главного окна

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

Давайте рассмотрим первый случай, когда форма авторизации пользователя появляется без главного окна приложения.

В главной форме приложения (MDI-форме) следует написать следующий код:

procedure TfrmMDI.FormCreate(Sender: TObject);
var
  iniF: TIniFile;
  sServer, sPort, sUser, sPassword, sConnection: string;//Строка соединения с БД.
begin
  sTekPapka:=getcurrentdir;
  try
    frmMDI.AlphaBlendValue:=0; //Прячем главную форму (делаем ее полностью прозрачной)
    ADOConnection1.Close;//Закрываем соединение с БД
    //Считываем данные из файла Конфиг.
    //Для этого создаем объект файла Конфиг
    iniF:=TiniFile.Create(STekPapka+'\Config.ini');
    //Считываем содержимое файла Конфиг и заносим значения в форму
    sServer:=iniF.ReadString('DB', 'Server','');
    sPort:=iniF.ReadString('DB', 'Port','');
    sUser:=iniF.ReadString('DB', 'User','');
    sPassword:=iniF.ReadString('DB', 'Password','');
    iniF.free;
    sConnection:='Provider=MSDASQL.1;Persist Security Info=False;Extended Properties="Driver=MySQL ODBC 8.0 Unicode Driver;SERVER='+sServer+';UID='+sUser+';password='+sPassword+';DATABASE=bus_station;PORT='+sPort+';charset=cp1251;COLUMN_SIZE_S32=1"';
    ADOConnection1.ConnectionString:=sConnection;
    ADOConnection1.Open; // Открываем соединение
  except
    Application.CreateForm(TfrmConnection,frmConnection);
    frmConnection.Show;
  end;
end;

Давайте разберем этот код... Секция var содержит объявления переменных двух типов. Один тип TIniFile. Другой String.

var
  iniF: TIniFile;
  sServer, sPort, sUser, sPassword, sConnection: string;//Строка соединения с БД.

Я использую тип TIniFile для хранения данных о подключении и параметрах программы в INI-файле. Это является несколько устаревшим подходом, но он прост, понятен и до сих пор активно используется в виду того, что с помощью него можно хранить любые параметры настроек. Мне так же нравится этот подход.

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

Могут еще храниться разные параметры подключения, но перечисленные являются основными. И чтобы каждый раз при запуске программы не вводить их, удобно было бы хранить их в конфигурационном INI файле, так и назвав его, например, Config.ini.

Переменные sServer, sPort, sUser, sPassword будут содержать значения этих самых параметров подключения, которые будут считаны с Config.ini и присвоены нашим переменным.

Содержимое Config.ini может выглядеть следующим образом:

[ORG]
   NumberParking=1
   NameOrg=ЗАО "Парковка"
   FIORuk=Маковозов Михаил Арсеньевич
   DolRuk=Директор
   FIOGlBuh=Михайлова Дарья Александровна
   INN=3123351893
   KPP=332901001
   BANK=Отделения и филиалы Сбербанка в г. Белогорода. Дополнительный офис № 8627/01357
   RS=40703810777020000308
   KS=30101810100000000612
   BIK=042908612
   UrAdres=308001, г. Белгород, ул. Вокзальная, 33а.
   PostAdres=308001, г. Белгород, ул. Вокзальная, 33а.
   OGRN=1105543026445
   OKVD=18.1
   Telefon=+7 (4722) 32-14-96, +7 (4722) 40-23-54
   Website=https://belparking.ru
[DB]
   Server=localhost
   Port=3306
   User=root
   Password=1234

Данный файл состоит из секций. В данном случае у меня их всего две: [ORG] и [DB].

Эти секции служат для группировки данных файла (для удобства восприятия). Как видите, в секции [ORG] я храню информацию об организации, а в секции [DB] я храню информацию о подключении к базе данных. Конечно название секций и способ хранения — условны. Например, информацию об организации удобно хранить не в таком файле, а в самой базе данных, поскольку при многопользовательском доступе такой Config.ini в отношении реквизитов организации придется настраивать ан каждом компьютере, а это не удобно. Но все же мы оставим этот вопрос, ведь здесь мы рассматриваем гипотетический пример.

Итак, идем дальше. У нас есть еще одна переменная sConnection. Она будет содержать в себе строку подключения. Еще одной важной переменной, которая будет глобальной является sTekPapka. Она будет содержать в себе путь к каталогу, из которого мы запустили нашу программу. То есть, текущий каталог программы. Ее следует объявить в модуле главной формы приложения в секции для объявления глобальных переменных.

Далее мы получаем наш текущий каталог и для того, чтобы показать отдельно нашу форму авторизации без главного окна приложения, мы просто делаем полную прозрачность нашему главному окну посредством установки свойства frmMDI.AlphaBlendValue:=0.

Отлично. Теперь, на всякий случай, закрываем соединение, считываем наши параметры подключения из файла Config.ini и присваиваем их нашим описанным выше переменным. А затем в переменной sConnection мы объединяем все это в одну строку подключения к базе данных.

В данном случае, в качестве базы данных у меня используется база с именем bus_station. У вас будет свое имя базы данных. О том, как подключиться к базе данных я рассказываю в своей статье Подключение к базе данных в Delphi.

Затем мы присваиваем нашу сформированную строку подключения свойству ConnectionString объекта adoConnection и открываем наше соединение.

В примере я использую технологию ADO, поэтому использую объект соединения с базой данных adoConnection. Вы также можете использовать аналогичные объекты из других библиотек. Затем соединение открывается.

Если же при подключении к базе данных возникает ошибка, мы выводим форму, сообщающую пользователю о том, что подключение не состоялось, либо, как у меня в промере, форму для того, чтобы указать параметры подключения. В данном случае в этой форме при ее создании можно также считать эти параметры подключения из файла Config.ini.

except
    Application.CreateForm(TfrmConnection,frmConnection);
    frmConnection.Show;
  end;

Например, это может выглядеть вот так:

Настройка подключения к базе данных
Форма настроек подключения к базе данных

В данном случае пользователю нужно изменить данные, нажать сохранить и перезапустить программу.

Поехали дальше... А дальше мы пишем в главной форме приложения в событии onShow такой код:

procedure TfrmMDI.FormShow(Sender: TObject);
begin
  //Создаем форму авторизации
  Application.CreateForm(TfrmLogin,frmLogin);
  frmLogin.Show;
end;

Форма авторизации Delphi в данном случае у нас будет называться frmLogin. И мы пишем в ней вот такой код:

Uses
    .....System.SysUtils, System.TypInfo.....;//Добавляем два модуля к существующим.

type
  TStrings = (Администраторы, Логисты, Кассиры);//Объявляем свой тип
...
//Объявляется класс формы

...
procedure TfrmLogin.FormCreate(Sender: TObject);
var
  KolZap: integer;
  TekZap: integer;
  i: integer; // Счетчик
begin
  //Прячем все пункты меню из главной формы приложения
  frmMDI.mnuAdmin.Visible:=false;
  frmMDI.mnuLogin.Visible:=false;
  frmMDI.mnuExit.Visible:=false;
  //Подключаемся к Таблице Логины
     adoLogin.Open;
     //Заполняем логинами раскрывающийся список
     cboLogin.Clear;
     KolZap:=adoLogin.RecordCount;
     adoLogin.First;
     TekZap:=adoLogin.RecNo;
     for i:=TekZap to KolZap do
     begin
       cboLogin.Items.Add(adoLogin.fieldbyname('Логин').AsString);
       adoLogin.Next;
     end;
    //Сортируем список
    cboLogin.Sorted:=true;
   //Ставим первое значение в спиcке по умолчанию
   cboLogin.ItemIndex:=0;
end;

В данном случае, смотрите. Я люблю сразу создавать для себя типы пользователей и хранить их в отдельной таблице в базе данных. Также я создаю для них отдельный тип данных, который после использую для проверки того, какой тип пользователя сделал вход в систему.

На форме есть две кнопки Вход и Отмена. На кнопке Вход в событии onClick пишем следующий код:

procedure TfrmLogin.cmdInputClick(Sender: TObject);
var
  sTiplist: TStrings;
  sPassword: string;
begin
  sLogin:=cboLogin.Text;//Выбранный из списка логин
  sPassword:=trim(txtPassword.Text);//Введенный пользователем пароль
  //Теперь проверяем пароль, который ввел пользователь
  adoLogin.First;//Ставим указатель на первую запись таблицы
  adoLogin.Locate('Логин', sLogin,[]);// Находим в таблице запись с выбранным логином
  if adoLogin.fieldbyname('Пароль').AsString = sPassword then //Если пароль совпадает с введенным, то
  begin
    sTipUser:=StringReplace(adoLogin.fieldbyname('Тип').AsString, ' ',
    '_',[rfReplaceAll, rfIgnoreCase]);
    sTiplist:=TStrings(GetEnumValue(TypeInfo(TStrings), sTipUser));
    case sTiplist of
         Администраторы:
         begin
           frmMDI.mnuAdmin.Visible:=true;
           frmMDI.mnuLogist.Visible:=true;
           frmMDI.mnuSales.Visible:=true;
           frmMDI.mnuLogin.Visible:=true;
           frmMDI.mnuExit.Visible:=true;
         end;
         Логисты:
         begin
           frmMDI.mnuAdmin.Visible:=false;
           frmMDI.mnuLogist.Visible:=true;
           frmMDI.mnuSales.Visible:=false;
           frmMDI.mnuLogin.Visible:=true;
           frmMDI.mnuExit.Visible:=true;
         end;
         Кассиры:
         begin
           frmMDI.mnuAdmin.Visible:=false;
           frmMDI.mnuLogist.Visible:=false;
           frmMDI.mnuSales.Visible:=true;
           frmMDI.mnuLogin.Visible:=true;
           frmMDI.mnuExit.Visible:=true;
         end;
    end;
    //Раз пароль подошел, то получаем из записи таблицы БД остальные
    //характеристики пользователя
    iIDUser:=adoLogin.fieldbyname('ID_пользователя').AsInteger;
    sFIOUser:=adoLogin.fieldbyname('ФИО').AsString; //Присваиваем ФИО сотрудника, вошедшего в систему из набора
    sDolgnostUser:=adoLogin.fieldbyname('Должность').AsString;
    //Устанавливаем для главной формы заголовок
    frmMDI.Caption:='Автовокзал - '+'Пользователь: '+sLogin+'      '+'ФИО: '+sFIOUser+'      '+'Тип: '+sTipUser+'      '+'Должность: '+sDolgnostUser;
    frmMDI.AlphaBlendValue:=255;//Делаем главную форму видимой
    Close;//и закрываем окно авторизации
  end else //Если введенный пароль не совпал с тем, который в записи, то
  //выводим окно с сообщением.
  begin
    Application.CreateForm(TfrmGray,frmGray);//Вызываем окно-темную подложку
    Application.CreateForm(TfrmMessage,frmMessage);
    frmMessage.Left:=Round(Left +(Width-frmMessage.Width)/2);
    frmMessage.Top:=Round(Top +(Height-frmMessage.Height)/2+20);
    frmMessage.lblMessage.Caption:='Пароль не верный! Обратитесь к администратору системы!';
    frmMessage.ShowModal();
    frmGray.Close;
  end;
end;

Кнопка Отмена будет содержать довольно простой код:

procedure TfrmLogin.cmdCancelClick(Sender: TObject);
begin
     Application.Terminate //завершаем приложение
end;

Надо иметь ввиду, что это довольно простой код и его можно всячески усовершенствовать. Плюс ко всему для его работы у меня используются дополнительные формы, такие как frmMessage, frmGray, которые я создавал заранее. Можно не использовать, например frmGray, которая создает затемнение перед показом модального окна с сообщением frmMessage. Можно не использовать frmMessage, а использовать вместо него встроенные в Delphi функции вывода сообщений.

В этом посте я просто хотел показать один из интересных подходов к созданию форм авторизации в системе программирования Delphi. Если кому то что-то не понятно, вы можете задать вопросы, на которые я постараюсь ответить.

В следующем посте рассмотрим, как создавать простые формы авторизации в приложении SDI-типа.

Понравилась статья? Поделиться с друзьями:
Блог Алексея Иванкова
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: