# Аутентификация

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

В этот статье рассматривается процесс аутентификации, а правам доступа посвящена одноименная [стать](https://wfsys.gitbook.io/wt-knowledge-base/platform-wt/access-rights).

{% hint style="info" %}
Аутентификация - процедура проверки подлинности, например проверка подлинности пользователя путем сравнения введенного им пароля с паролем, сохраненным в базе данных.

Авторизация - предоставление определенному лицу или группе лиц прав на выполнение определенных действий.
{% endhint %}

## Список пользователей <a href="#users-list" id="users-list"></a>

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

В базе данных в таблице **public.user** хранится общий список пользователей системы:

<figure><img src="https://705744344-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVZ4foBjMM8Ahva3mdZKf%2Fuploads%2F1JGlL10RQYvJAEvAR9aI%2Fimage.png?alt=media&#x26;token=3809b79f-9986-4eb8-a6a5-281abb23497d" alt=""><figcaption></figcaption></figure>

Описание полей таблицы:

* user\_id - идентификатор глобального пользователя;
* user\_name - логин глобального пользователя;
* user\_full\_name - полное имя глобального пользователя;
* person - признак, определяющий, является ли данный глобальный пользователь реальным пользователем;
* enabled - признак, определяющий, является ли данный глобальный пользователь включенным;
* language\_id - идентификатор языка глобального пользователя;
* time\_zone\_info\_id - идентификатор временной зоны глобального пользователя;
* user\_password - хеш пароля глобального пользователя.

В таблице есть записи системных пользователей:

* *Служба Workflow Engine* ($workflow\_engine$) - системный пользователь службы Workflow Engine, от имени которого совершаются некоторые автоматические действия с данными в базе данных;
* *WS. Гость* (WS\_GUEST) - системный пользователь, под которым запускается клиентское приложение.

Пользователи *Администратор*, *Пользователь 1* и *Пользователь 2* - реальный пользователь, под которым можно работать в программе. Реальный пользователь *Пользователь 3* отключен  (enabled = false) и под ним нельзя будет работать в  WT-программе.

Таблица **template.user** содержит идентификаторы пользователей, которые имеют доступ к бизнес-процессу Template:

<figure><img src="https://705744344-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVZ4foBjMM8Ahva3mdZKf%2Fuploads%2FxfeiTo2aU2nfvZtXSR4E%2Fimage.png?alt=media&#x26;token=c9686ac2-3df8-4563-92c6-786f46df98f7" alt=""><figcaption></figcaption></figure>

Так же в эту таблицу можно добавить поля для индивидуальных пользовательских настроек, например, для доступа к какому-нибудь отчету.

{% hint style="info" %}
WT-приложение может объединять несколько программ для разных бизнес-процессов, например, для автомойки и шиномонтажа.

Каждая программа будет иметь свой набор xml-файлов форм и свой серверный xml-файл с запросами. И, в большинстве случаев, серверная часть у них будет одна - нет смысла специально разделать серверные части, если в этом нет потребности. А значит, и базу данных можно использовать одну, но для каждого бизнес-процесса делать отдельную схему, чтобы разделить таблицы и функции.

Несмотря на то, что автомойка и шиномонтаж разные программы, какие-то пользователи могут иметь доступ к обеим программам, например, администраторы. Таким образом, в таблице *public.user* будут храниться логин и пароль, а так же пользовательские настройки, общие для автомойки и шиномонтажа. А в таблицах *carwash.user* (автомойка) и *tireservice.user* (шиномонтажа) будут храниться настройки пользователей, характерные для каждой программы. Например, доступ к какому-нибудь отчету.
{% endhint %}

## Процесс аутентификации

Как происходит аутентификация и авторизация в WT-программе

### 1. Форма входа

Когда пользователь запускает программу, открывается форма входа в программу:

<figure><img src="https://705744344-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVZ4foBjMM8Ahva3mdZKf%2Fuploads%2FAMzvdxioopd2Ryp4A6Y9%2Fimage.png?alt=media&#x26;token=c5e2cbdb-c756-4003-8d13-ad08425c1c52" alt=""><figcaption></figcaption></figure>

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

### 2. Запрос на список пользователей

Когда открывается форма аутентификации, на сервер отправляется запрос на получение списка пользователей. Все запросы к серверу подписываются учеткой текущего пользователя программы. Так как вход в программу еще не осуществлен, то запрос на список активных пользователей подписывается гостевой учеткой WS\_GUEST, [логин](https://wfsys.gitbook.io/wt-knowledge-base/platforma-wt/configuration-files/workflowforms.dll.config#anonymous_user_name) и [пароль](https://wfsys.gitbook.io/wt-knowledge-base/platforma-wt/configuration-files/workflowforms.dll.config#anonymous_password) которой указаны в конфиге клиентской части ([WorkflowForms.dll.config](https://wfsys.gitbook.io/wt-knowledge-base/platforma-wt/configuration-files/workflowforms.dll.config)).&#x20;

Список пользователей формируется с помощью SQL-запроса вида:

{% code title="Template.xml" %}

```xml
<SqlQuery Name="UserLoginSelectSqlQuery">
  <Text>
    SELECT
      user_id AS "UserId",
      user_name AS "UserName",
      user_full_name AS "UserFullName"
    FROM
      template.user_info UI
      JOIN template.user_group UG USING(user_id)
      JOIN template.group G USING (group_id)
    WHERE
      UI.person AND NOT UI.archive AND
      G.name IS DISTINCT FROM 'GuestGroup';
  </Text>
</SqlQuery>
```

{% endcode %}

В запросе используется **template.user\_info** - это представление, которое динамически строится на основе двух таблиц: **template.user** и **public.user**.

{% hint style="info" %}
В PostgreSQL представление (VIEW) - это виртуальная таблица, созданная запросом joins, соединяющим одну или несколько таблиц.

Про представления в PostgreSQL можно почитать в официальном документации по [ссылке](https://postgrespro.ru/docs/postgrespro/15/sql-createview).
{% endhint %}

### 3. Команда входа

На форме входа пользователь выбирает в выпадающем списке свою учетку и вводит пароль. По кнопке "Войти", клиентская часть хеширует введенный пароль безопасным алгоритмом *SHA-512* и отправляет на сервер запрос с логином и хешом пароля в зашифрованном виде, используя для этого  команду типа [LoginCommand](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/commands/login_command) .

### 4. Аутентификация на сервере

Когда запрос приходит на сервер, он попадает сначала в веб-сервер Kestrel, на котором запущена веб-служба, а затем перенаправляется в серверное приложение.

{% hint style="info" %}
Kestrel представляет кроссплатформенный веб-сервер и по умолчанию включается в проект ASP.NET Core.
{% endhint %}

На сервере механизм аутентификации и авторизации реализован с помощью JWT-токенов. Когда Workflow Engine получает запрос на аутентификацию пользователя, полученные логин и хеш пароля сверяются с теми, которые хранятся в таблице *public.user* в базе данных. Если логин и хеш пароля совпали - генерируется JWT-токен, который возвращается клиентскому приложению вместе с временем жизни этого токена и одноразовым токеном для повторной генерации основного JWT-токена.

{% hint style="info" %}
JWT (или JSON Web Token) представляет собой веб-стандарт, который определяет способ передачи данных о пользователе в формате JSON в зашифрованном виде.
{% endhint %}

### 5. Использование токенов

Клиентское приложение хранит JWT-токен и подписывает им все последующие запросы к серверу. Так же клиентская часть сама отслеживает время жизни JWT-токена: если JWT-токен устарел, то отправит запрос на обновление основного JWT-токена.

### 6. Авторизация на сервере при запросе

Сервер, получив запрос от клиентской части, проверяет JWT-токен, которым подписан запрос. Если токен актуален, то авторизация считается успешной, и происходит проверка [Прав доступа](https://wfsys.gitbook.io/wt-knowledge-base/platform-wt/access-rights) у пользователя на выполнение запроса или команды.
