Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Безопасное управление аутентификацией в Delphi приложениях: как хранить и обновлять OAuth 2.0 токены и безопасно управлять API ключами в REST клиентах?

Delphi , Синтаксис , Пароли

 

В современном мире интеграции с REST API безопасная обработка аутентификации становится критически важной задачей для разработчиков Delphi. В этой статье мы рассмотрим лучшие практики работы с OAuth 2.0, JWT и API ключами, а также безопасные способы хранения и обновления токенов.

Основные проблемы аутентификации в Delphi

При работе с REST API разработчики сталкиваются с несколькими ключевыми проблемами:

  1. Безопасное хранение учетных данных
  2. Управление сроком действия токенов
  3. Защита от несанкционированного доступа
  4. Обновление истекших токенов

Хранение API ключей и токенов

1. Шифрование чувствительных данных

Как правильно отметил Angus Robertson, API ключи и токены следует рассматривать как пароли и хранить их в зашифрованном виде. Вот пример использования шифрования в Delphi:

uses System.NetEncoding, DCPcrypt2, DCPsha256, DCPrijndael;

function EncryptString(const AText, APassword: string): string;
var
  Cipher: TDCP_rijndael;
begin
  Cipher := TDCP_rijndael.Create(nil);
  try
    Cipher.InitStr(APassword, TDCP_sha256);
    Result := Cipher.EncryptString(AText);
    Cipher.Burn;
  finally
    Cipher.Free;
  end;
end;

function DecryptString(const AText, APassword: string): string;
var
  Cipher: TDCP_rijndael;
begin
  Cipher := TDCP_rijndael.Create(nil);
  try
    Cipher.InitStr(APassword, TDCP_sha256);
    Result := Cipher.DecryptString(AText);
    Cipher.Burn;
  finally
    Cipher.Free;
  end;
end;

2. Использование Windows Credential Manager

Как предложил Die Holländer, для хранения учетных данных можно использовать встроенный Credential Manager Windows. Библиотека VSoft.WindowsCredentialManager (https://github.com/VSoftTechnologies/VSoft.WindowsCredentialManager) упрощает эту задачу:

uses VSoft.WindowsCredentialManager;

procedure SaveCredentials;
var
  CredMgr: ICredentialManager;
begin
  CredMgr := TCredentialManager.Create;
  CredMgr.SaveCredential('MyApp_API', 'client_id', 'secret_value');
end;

function LoadCredentials: string;
var
  CredMgr: ICredentialManager;
begin
  CredMgr := TCredentialManager.Create;
  Result := CredMgr.GetCredential('MyApp_API');
end;

Работа с OAuth 2.0 токенами

1. Хранение и обновление токенов

При работе с OAuth 2.0 важно правильно обрабатывать истечение срока действия токенов. Вот пример класса для управления токенами:

type
  TOAuthTokenManager = class
  private
    FAccessToken: string;
    FRefreshToken: string;
    FExpiresAt: TDateTime;
    FClientID: string;
    FClientSecret: string;
  public
    constructor Create(const AClientID, AClientSecret: string);
    function IsTokenExpired: Boolean;
    function GetAccessToken: string;
    procedure RefreshToken;
  end;

constructor TOAuthTokenManager.Create(const AClientID, AClientSecret: string);
begin
  FClientID := AClientID;
  FClientSecret := AClientSecret;
end;

function TOAuthTokenManager.IsTokenExpired: Boolean;
begin
  Result := Now >= FExpiresAt;
end;

procedure TOAuthTokenManager.RefreshToken;
var
  RESTClient: TRESTClient;
  RESTRequest: TRESTRequest;
  RESTResponse: TRESTResponse;
begin
  RESTClient := TRESTClient.Create('https://oauth.provider.com');
  RESTRequest := TRESTRequest.Create(nil);
  RESTResponse := TRESTResponse.Create(nil);
  try
    RESTRequest.Client := RESTClient;
    RESTRequest.Response := RESTResponse;
    RESTRequest.Method := rmPOST;
    RESTRequest.Resource := 'token';
    RESTRequest.AddParameter('grant_type', 'refresh_token', pkGETorPOST);
    RESTRequest.AddParameter('refresh_token', FRefreshToken, pkGETorPOST);
    RESTRequest.AddParameter('client_id', FClientID, pkGETorPOST);
    RESTRequest.AddParameter('client_secret', FClientSecret, pkGETorPOST);

    RESTRequest.Execute;

    if RESTResponse.StatusCode = 200 then
    begin
      FAccessToken := RESTResponse.JSONValue.GetValue<string>('access_token');
      FRefreshToken := RESTResponse.JSONValue.GetValue<string>('refresh_token');
      FExpiresAt := Now + RESTResponse.JSONValue.GetValue<Integer>('expires_in') / SecsPerDay;
    end
    else
      raise Exception.Create('Token refresh failed');
  finally
    RESTResponse.Free;
    RESTRequest.Free;
    RESTClient.Free;
  end;
end;

function TOAuthTokenManager.GetAccessToken: string;
begin
  if IsTokenExpired then
    RefreshToken;
  Result := FAccessToken;
end;

2. Использование Azure Key Vault

Как упомянул Lars Fosdal, для облачных приложений хорошим решением может быть Azure Key Vault. Вот пример работы с ним:

uses Azure.API, System.Threading;

function GetSecretFromAzureVault(const VaultURL, SecretName, ClientID, ClientSecret: string): string;
var
  AzureClient: TAzureClient;
begin
  AzureClient := TAzureClient.Create;
  try
    AzureClient.SetCredentials(ClientID, ClientSecret);
    Result := AzureClient.GetSecret(VaultURL, SecretName);
  finally
    AzureClient.Free;
  end;
end;

Альтернативные решения

1. Использование аппаратных идентификаторов

Как отметил GabrielMoraru, получение стабильного аппаратного идентификатора на Windows может быть сложной задачей. Однако можно использовать комбинацию нескольких параметров:

function GetDeviceFingerprint: string;
var
  VolumeSerial: DWORD;
  ComputerName: array[0..MAX_COMPUTERNAME_LENGTH] of Char;
  Size: DWORD;
begin
  // Получаем серийный номер системного диска
  GetVolumeInformation('C:\', nil, 0, @VolumeSerial, nil, nil, nil, 0);

  // Получаем имя компьютера
  Size := MAX_COMPUTERNAME_LENGTH;
  GetComputerName(ComputerName, Size);

  // Комбинируем для создания "отпечатка"
  Result := Format('%s-%x', [ComputerName, VolumeSerial]);
end;

2. Многоуровневая аутентификация

Как предложил Patrick PREMARTIN, можно реализовать многоуровневую систему аутентификации:

type
  TAPIAuthLevel = (alAnonymous, alUser, alAdmin, alSystem);

  TAPIClient = class
  private
    FUserID: string;
    FAppID: string;
    FDeviceID: string;
    FAuthLevel: TAPIAuthLevel;
  public
    constructor Create(const AUserID, AAppID, ADeviceID: string; AAuthLevel: TAPIAuthLevel);
    function GenerateRequestSignature(const RequestData: string): string;
  end;

constructor TAPIClient.Create(const AUserID, AAppID, ADeviceID: string; AAuthLevel: TAPIAuthLevel);
begin
  FUserID := AUserID;
  FAppID := AAppID;
  FDeviceID := ADeviceID;
  FAuthLevel := AAuthLevel;
end;

function TAPIClient.GenerateRequestSignature(const RequestData: string): string;
var
  Hash: TDCP_sha256;
  Digest: array[0..31] of Byte;
  I: Integer;
begin
  Hash := TDCP_sha256.Create(nil);
  try
    Hash.Init;
    Hash.UpdateStr(FUserID + FAppID + FDeviceID + RequestData);
    Hash.Final(Digest);

    Result := '';
    for I := 0 to 31 do
      Result := Result + IntToHex(Digest[I], 2);
  finally
    Hash.Free;
  end;
end;

Лучшие практики безопасности

  1. Никогда не храните секреты в коде - как отметил Patrick PREMARTIN, даже приватные репозитории не являются безопасным местом для хранения ключей.

  2. Используйте HTTPS - все API вызовы должны выполняться только через защищенные соединения.

  3. Реализуйте минимальные необходимые права - предоставляйте приложению только те права, которые ему действительно необходимы.

  4. Регулярно обновляйте токены - не ждите истечения срока действия, обновляйте токены заранее.

  5. Логируйте события аутентификации - но не сами учетные данные.

Заключение

Безопасная аутентификация в Delphi приложениях требует комплексного подхода. В зависимости от требований вашего приложения вы можете выбрать один из рассмотренных методов или их комбинацию. Windows Credential Manager и Azure Key Vault предоставляют надежные решения для хранения секретов, а правильная реализация OAuth 2.0 клиента обеспечит безопасное взаимодействие с REST API.

Помните, что безопасность - это процесс, а не разовое мероприятие. Регулярно пересматривайте и обновляйте свои решения в соответствии с новыми угрозами и лучшими практиками.

Создано по материалам из источника по ссылке.

В статье рассматриваются лучшие практики безопасной аутентификации в Delphi приложениях при работе с REST API, включая хранение API ключей и токенов, работу с OAuth 2.0, использование Azure Key Vault и другие альтернативные решения.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: Пароли ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-04-23 05:31:25/0.0057220458984375/1