Электронная подпись вложений (Attachment Signature)
Обзор
В UniBPM реализован серверный механизм электронной подписи документов
(вложений типа Attachment), обеспечивающий:
- контроль целостности документа
- фиксацию данных подписанта
- фиксацию контекста аутентификации
- неизменяемость подписи
- возможность последующей проверки
❗️Механизм предназначен для внутреннего корпоративного документооборота и не является квалифицированной электронной подписью (КЭП).
Архитектура подписи
1. Контроль целостности документа
docHash = SHA-256(байты PDF)
Позволяет определить, был ли изменён документ после подписания.
2. Контекст аутентификации (Auth Context)
Формируется JSON-снимок контекста пользователя без сохранения Bearer token.
Вычисляется:
authContextHash = SHA-256(authContextJson)
3. Payload подписи
Формируется канонический JSON:
{
"signatureId": "...",
"docId": "...",
"docHash": "...",
"signerUserId": "...",
"signerFullName": "...",
"signerPosition": "...",
"signerEmployeeId": "...",
"signerBusinessUnit": "...",
"signerLegalEntity": "...",
"signerRole": "...",
"signedAt": "...",
"authContextHash": "...",
"systemVersion": "1.0.0",
"signatureAlgorithm": "SHA-256"
}
Вычисляется:
signaturePayloadHash = SHA-256(signaturePayloadJson)
Хранение данных
JSON сохраняется в БД в формате TEXT для обеспечения стабильности хеша.
API
Использование в UI (Filepicker)
Для включения механизма подписи в форме используется компонент filepicker.
Custom Properties
{
"signature": "true",
"signerRole": "EMPLOYEE",
"signatureReadonly": "true"
}
signature = true— включает механизм подписи для вложенияsignerRole— роль подписанта (передаётся на backend при подписании)signatureReadonly = true— режим только просмотра подписи (подписание недоступно)
Поведение компонента
Компонент отображает строку вида:
Не подписано • Подписать • Протокол подписания • Скачать с штампом
Статусы подписи:
- Не подписано
- Подписано вами
- Подписано другим сотрудником
- Подпись не действительна
Логика:
- Подписать — доступно, если документ не подписан или подписан другим пользователем и не установлен
signatureReadonly = true - Протокол подписания — доступно, если есть подписи
- Скачать с штампом — доступно, если есть подписи
При клике на имя файла выполняется скачивание оригинального документа.
Подписать документ
POST /api/attachment/{id}/sign
Получить список подписей
GET /api/attachment/{id}/signatures
Проверить подписи
GET /api/attachment/{id}/verify
Получить протокол подписи
GET /api/attachment/{id}/signature-protocol
Возвращает PDF-документ с протоколом подписания вложения.
Протокол содержит:
- сведения о документе (идентификатор, имя файла, размер, тип)
- сводную таблицу подписей
- детальную информацию по каждой подписи
- хэш документа (SHA-256)
- хэш контекста аутентификации (authContextHash)
- хэш payload подписи (signaturePayloadHash)
- JSON контекста аутентификации
- JSON payload подписи
Документ предназначен для:
- аудита подписания
- передачи в архив
- последующей проверки корректности подписей
Формат ответа: application/pdf
Получить документ со штампом подписей
GET /api/attachment/{id}/signature-stamped
Возвращает исходный PDF-документ с наложенным штампом подписей на последней странице.
Штамп содержит:
- надпись «Документ подписан электронной подписью (UniBPM)»
- таблицу подписантов:
- №
- Подписант
- Должность
- Организация
- Дата и время подписания
- общее количество подписей
- хэш документа (SHA-256)
Особенности:
- штамп накладывается поверх документа без изменения исходного содержимого
- используется компактное представление, оптимизированное для печати
- применяется единый акцентный стиль UniBPM
- поддерживается корректное отображение кириллицы
Формат ответа: application/pdf
Назначение:
- предоставление пользователю финальной версии документа с подписями
- визуальное подтверждение подписания
- передача документа внешним системам и контрагентам
Получить оригинальный документ
GET /api/attachment/read/{id}
Возвращает исходный файл вложения без изменений.
Особенности:
- используется для скачивания оригинального документа
- возвращает бинарные данные (blob)
- применяется в UI при клике на имя файла
Формат ответа: соответствует типу файла (например, application/pdf)
Предварительная настройка Keycloak
Требуемые claims
{
"signerEmployeeId": "0000-00006",
"signerLegalEntity": "ООО \"Ромашка\"",
"signerBusinessUnit": "Административный департамент",
"signerFullName": "Иванов Иван Иванович",
"signerPosition": "Генеральный директор"
}
Создание атрибутов
Admin Console → Realm → Realm Settings → User Profile
Создать атрибуты:
- signerFullName
- signerPosition
- signerBusinessUnit
- signerEmployeeId
- signerLegalEntity
❗️После создания атрибутов необходимо обеспечить их заполнение и поддержание в актуальном состоянии.
Настройка client scope
Создать client scope и добавить мапперы типа User Attribute → Claim.
Пример для signerFullName:
- Mapper Type: User Attribute
- User Attribute: signerFullName
- Token Claim Name: signerFullName
- Claim JSON Type: String
- Add to access token: true
- Add to ID token: true
- Add to userinfo: true
- Multivalued: false
Повторить для остальных атрибутов.
Настройка properties UniBPM
application:
signature:
claims:
mapping:
full-name: signerFullName
position: signerPosition
business-unit: signerBusinessUnit
employee-id: signerEmployeeId
legal-entity: signerLegalEntity
missing-claim-policy: FAIL
Политики:
- FAIL — подписание запрещено
- EMPTY — сохраняется пустое значение
- FALLBACK — используется альтернативное значение
Рекомендуется FAIL.
Гарантии механизма
- контроль неизменности документа
- фиксация версии системы
- фиксация алгоритма подписи
- проверяемость подписи в будущем
Ограничения
- Не является квалифицированной ЭП
- Использует SHA-256
- Подпись формируется на сервере