Авторизации в C# .NET
Пример обращения к web-серверу, получения и обработки результата реализован на языке C#[7] в среде .NET[8] версии 8.0.13.
Взаимодействие с сервером осуществляется через объект класса HttpClient[9].
Классы объектов, отправляемых в запросах и получаемых в ответах, берутся из библиотек ПОЛИНОМ:MDM Polynom.Web.Api.Data и Polynom.Web.Api.Models.
ВНИМАНИЕ: применяемость токена входа истекает через 10 минут после его создания. Для продолжения работы нужно использовать токен обновления.
Создание Http-клиента
// Получаем адрес сервера
var serverAddress = "http://localhost:5000";
// Проверяем адрес сервера
if (!Uri.TryCreate(serverAddress, UriKind.Absolute, out var baseAddress))
throw new ArgumentException("Ошибка адреса web-сервера ПОЛИНОМ:MDM");
// Создаем экземпляр класса HttpClient
var client = new HttpClient()
{
BaseAddress = baseAddress
};
Получение списка зарегистрированных хранилищ
Определение StorageDefinitionResponse
/// <summary>
/// Модель данных ответа на запрос описаний хранилищ.
/// </summary>
public class StorageDefinitionResponse
{
/// <summary>
/// Идентификатор хранилища.
/// </summary>
public Guid StorageId { get; set; }
/// <summary>
/// Отображаемое имя хранилища.
/// </summary>
public string DisplayName { get; set; } = null!;
}
Запрос и чтение ответа:
// Запрашиваем описание хранилищ
List<StorageDefinitionResponse> storages;
using (var response = await client.GetAsync("api/v1/login/storage-definitions", CancellationToken.None))
{
response.EnsureSuccessStatusCode();
storages = await response.Content.ReadFromJsonAsync<List<StorageDefinitionResponse>>(
cancellationToken: CancellationToken.None) ?? new List<StorageDefinitionResponse>();
}
var storageId = storages.FirstOrDefault(c => c.DisplayName == storageName)?.StorageId ??
throw new Exception("Хранилище не найдено");
Вход
Определение SignInRequest
/// <summary>
/// Тип клиентов ПОЛИНОМ:MDM.
/// </summary>
public enum ClientTypes : byte
{
/// <summary>
/// Нет типа.
/// </summary>
None = 0,
/// <summary>
/// Клиент.
/// </summary>
Client = 8,
/// <summary>
/// Конвертер.
/// </summary>
Importer = 16,
/// <summary>
/// Редактор.
/// </summary>
Editor = 32,
/// <summary>
/// Администратор.
/// </summary>
Administrator = 64
}
/// <summary>
/// Модель данных для авторизации пользователя
/// </summary>
public class SignInRequest
{
/// <summary>
/// Идентификатор хранилища.
/// </summary>
public string StorageId { get; set; } = null!;
/// <summary>
/// Имя пользователя ПОЛИНОМ:MDM.
/// </summary>
public string? Login { get; set; }
/// <summary>
/// Пароль.
/// </summary>
public string? Password { get; set; }
/// <summary>
/// Имя модуля.
/// </summary>
public string? ModuleName { get; set; }
/// <summary>
/// Указывает тип клиента.
/// </summary>
public ClientTypes? ClientType { get; set; }
}
Определение AuthResponse
/// <summary>
/// Ответ на авторизацию пользователя.
/// </summary>
public class AuthResponse
{
/// <summary> Токен доступа. </summary>
[JsonPropertyName("access_token")]
public string AccessToken { get; set; } = string.Empty;
/// <summary> Тип токена доступа. </summary>
[JsonPropertyName("token_type")]
public string TokenType { get; set; } = "Bearer";
/// <summary> Срок жизни токена доступа. (сек.) </summary>
[JsonPropertyName("expires_in")]
public int ExpiresIn { get; set; } = 600;
/// <summary> Токен обновления токена доступа. </summary>
[JsonPropertyName("refresh_token")]
public string? RefreshToken { get; set; } = string.Empty;
}
Запрос и чтение ответа:
var signInRequest = new SignInRequest()
{
Login = username,
Password = password,
StorageId = storageId.ToString(),
ClientType = ClientType.Client
};
AuthResponse? authResponse;
using (var jsonContent = JsonContent.Create(signInRequest))
{
using (var response = await client.PostAsync(@"api/v1/login/sign-in", jsonContent, CancellationToken.None))
{
response.EnsureSuccessStatusCode();
authResponse =
await response.Content.ReadFromJsonAsync<AuthResponse>(cancellationToken: CancellationToken.None);
if (authResponse is null)
throw new Exception("Ошибка получения данных ответа");
}
}
Сохранение токена для последующих запросов
Чтобы отправлять запросы web-серверу ПОЛИНОМ:MDM, нужно добавить полученный ранее токен в заголовки запроса.
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", authResponse.AccessToken);
Обновление токена входа
Запрос и чтение ответа:
// Обновление токена авторизации
using (var textContent = new StringContent(authResponse.RefreshToken, Encoding.UTF8, MediaTypeNames.Text.Plain))
{
// Обрабатываем ответ
using (var response = await client.PatchAsync("api/v1/login/update-token", textContent,
cancellationToken: CancellationToken.None))
{
response.EnsureSuccessStatusCode();
authResponse =
await response.Content.ReadFromJsonAsync<AuthResponse>(cancellationToken: CancellationToken.None);
if (authResponse is null)
throw new Exception("Ошибка получения данных ответа");
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(authResponse.TokenType, authResponse.AccessToken);
}
}
Выход
Запрос и чтение ответа:
using (var response = await client.DeleteAsync("api/v1/login/sign-out"))
{
response.EnsureSuccessStatusCode();
}
См. пример Samples.WebApi.Authorization
Ссылки
- Руководство по C# — управляемый язык .NET. (дата обращения: 16.07.2024).
- Загрузите .NET 8.0 (Linux, macOS и Windows). (дата обращения: 16.07.2024).
- HttpClient Class (System.Net.Http). (дата обращения: 16.07.2024).