Аутентификация
Аутентификация — это первая часть взаимодействия с REST API. Она необходима для того, чтобы Jmix мог идентифицировать пользователя, выполняющего запрос. Это позволяет Jmix накладывать ограничения разрешений/доступа к данным на запросы, чтобы гарантировать, что пользователю мог видеть/взаимодействовать только с разрешенным ему частями системы.
Запрос аутентификации
Для взаимодействия с Jmix REST API требуется аутентификация через поток OAuth2. Краткий обзор представлен на следующей диаграмме последовательности:
Во-первых, клиент API должен запросить токен доступа через запрос аутентификации. Для этого нужно отправить запрос www-form-urlencoded
с именем пользователя и паролем как часть тела формы в Jmix:
POST http://localhost:8080/oauth/token
Authorization: Basic {{client_id}} {{client_secret}} (1)
Content-Type: application/x-www-form-urlencoded (2)
grant_type=password (3)
&username={{username}} (4)
&password={{password}}
1 | Сам Authentication Request аутентифицируется с помощью Basic Auth client_id и client_secret. |
2 | Содержимое запроса аутентификации – application/x-www-form-urlencoded . |
3 | Значение grant_type – password , чтобы обозначить тип логина. |
4 | Учетные данные пользователя предоставляются как часть формы с ключами username и password . |
После успешного входа в систему Jmix возвращает токен доступа как часть ответа HTTP:
{
"access_token": "CXE0w/9cOsnpSo8v2jEDoI8Qa3Y=",
"token_type": "bearer",
"refresh_token": "Hh2xCuZ7fgd35obagEBNGevF4ws=",
"expires_in": 31535999,
"scope": "rest-api",
"OAuth2.SESSION_ID": "5C46CDF266E8C8C15372887830B74F59"
}
Атрибут access_token
содержит токен, который вы можете использовать в дальнейших запросах: CXE0w/9cOsnpSo8v2jEDoI8Qa3Y=
.
Обновление токена
Токен действует как временные учетные данные/пароль. По истечении определенного периода срок действия токена истекает, и становится необходимо запросить новый. Первый вариант – снова запросить у пользователя его учетные данные и выполнить обычный запрос аутентификации.
Не храните имя пользователя и пароль в своем клиентском приложении, чтобы пользователю не нужно было повторно вводить свои учетные данные. Либо снова запросите у пользователя его учетные данные, либо используйте токен обновления, чтобы предотвратить истечение срока действия. |
Исходный Authentication Request содержит refresh_token
, который можно использовать для создания нового токена доступа. В то время как токен доступа сравнительно недолговечен (по умолчанию 12 часов для Jmix), токен обновления по умолчанию действителен в течение 365 дней. Поэтому он хорошо подходит в качестве долгоживущего способа для выпуска новых токенов.
Чтобы получить новый токен доступа с помощью токена обновления, вы можете использовать ту же операцию. Но вместо использования grand_type
: password
вы также можете использовать refresh_token
. Пример использования токена обновления:
POST http://localhost:8080/oauth/token
Authorization: Basic {{client_id}} {{client_secret}}
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token (1)
&refresh_token=Hh2xCuZ7fgd35obagEBNGevF4ws= (2)
1 | Значение grant_type – refresh_token , чтобы обозначить тип логина. |
2 | Токен обновления предоставляется как часть формы с ключом refresh_token . |
Ответ содержит новый токен доступа с новым сроком действия. При этом вы можете сохранить доступ к API без необходимости запрашивать у пользователя его учетные данные после истечения срока действия токена доступа.
Выполнение запросов к API
Существует два способа использования токена доступа для аутентификации в различных API-интерфейсах Jmix, в зависимости от варианта использования. Начнем с первого и основного: через HTTP-заголовок в следующих запросах.
Аутентификация через заголовок
С полученным токеном доступа CXE0w/9cOsnpSo8v2jEDoI8Qa3Y=
вы можете выполнять запросы к REST API. Токен необходимо передавать в качестве заголовка (Header) Authorization
в каждом запросе, как в следующем примере:
POST http://localhost:8080/rest
/entities
/rstex11_Customer
Authorization: Bearer CXE0w/9cOsnpSo8v2jEDoI8Qa3Y= (1)
{
name: "Randall Bishop"
}
1 | Запрос API аутентифицируется с помощью типа авторизации Bearer и полученного токена доступа. |
Аутентификация через параметр URL
Также можно передать токен доступа в качестве параметра запроса URL. Это необходимо, когда установить заголовок HTTP невозможно в случае ссылки браузера на файл или отображения изображения.
В следующем примере изображение из Files API должно отображаться на сайте через <img src="…" />
.
В этом случае установить заголовок HTTP невозможно. Передадим access_token
как параметр запроса URL:
<img
src="http://localhost:8080/files
?access_token=CXE0w/9cOsnpSo8v2jEDoI8Qa3Y=
&fileRef=fs://2021/03/12/a3b6011d-9040-151e-7d17-f7ccdf75d72f.jpg?name=cat.jpg"
/>
Анонимный доступ
По умолчанию все операции доступны только после успешной аутентификации в приложении. Но также возможно предоставить определенные части REST API и без аутентификации с помощью функции анонимного доступа Jmix. В этом случае запрос API выполняется от имени пользователя anonymous
, который настроен по умолчанию в приложении Jmix.
Для каждой защищенной операции, которая вызывается без заголовка Authentication
, пользователь будет аутентифицирован как anonymous
.
Чтобы внести определенные операции в белый список для анонимного доступа, задайте список шаблонов URL-адресов, разделенных запятыми, в свойстве приложения jmix.rest.anonymous-url-patterns. Например:
jmix.rest.anonymous-url-patterns = \
/rest/services/productService/getProductInformation,\
/rest/entities/Product,\
/rest/entities/Product/*
Последний шаблон в приведенном выше примере необходим, если вы хотите обновить или удалить объект Product
, потому что в этом случае URL-адрес имеет часть идентификатора.
Как только параметр установлен, можно взаимодействовать с ProductService
без отправки заголовка Authorization
:
GET {{baseRestUrl}}
/services
/productService
/getProductInformation
?productId=123
# Authorization: not set
На этот запрос вернется успешный ответ сервиса:
{
"name": "Apple iPhone",
"productId": "123",
"price": 499.99
}
Если вы хотите предоставить анонимный доступ к операциям некоторых сущностей, убедитесь, что у пользователя anonymous
есть права на эти сущности. Для этого создайте ресурсную роль и назначьте ее пользователю anonymous
в методе DatabaseUserRepository.initAnonymousUser()
. Например:
@ResourceRole(name = "AnonymousRestRole", code = AnonymousRestRole.CODE, scope = "API")
public interface AnonymousRestRole {
String CODE = "anonymous-rest-role";
@EntityAttributePolicy(entityClass = Product.class,
attributes = "*",
action = EntityAttributePolicyAction.MODIFY)
@EntityPolicy(entityClass = Product.class,
actions = {EntityPolicyAction.READ, EntityPolicyAction.UPDATE})
void product();
}
@Primary
@Component("UserRepository")
public class DatabaseUserRepository extends AbstractDatabaseUserRepository<User> {
// ...
@Override
protected void initAnonymousUser(User anonymousUser) {
Collection<GrantedAuthority> authorities = getGrantedAuthoritiesBuilder()
.addResourceRole(AnonymousRestRole.CODE)
.build();
anonymousUser.setAuthorities(authorities);
}
}
Функция анонимного доступа не требует наличия роли rest-minimal у пользователя anonymous .
|