You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将基于MVCFramework的Delphi REST API项目转为使用RAD Studio标准组件

解决方案:用RAD Studio自带REST.Client组件替代MVCFramework.RESTClient

核心问题分析

你遇到的SSL握手错误,是因为自带REST组件默认的SSL协议版本和目标服务器不兼容(原MVC代码明确指定了sslvSSLv23);而OAuth2的client_credentials模式,需要在TOAuth2Authenticator中正确配置授权类型。

关键配置与代码实现

1. 配置SSL协议版本

自带的TRESTClient底层依赖Indy,需要手动指定SSL协议为sslvSSLv23,和原代码保持一致,避免握手失败。

2. 正确设置OAuth2的client_credentials模式

使用TOAuth2Authenticator组件,将GrantType设为gtClientCredentials,并填入ClientID、ClientSecret以及授权地址TokenEndpoint。

3. 完整转换后的代码

function ConnectionTest_UsingRADRESTClient: Boolean;
var
  FBaseURL, FAuthURL, FClientID, FClientSecret: string;
  FRestClient: TRESTClient;
  FRestRequest: TRESTRequest;
  FOAuth2Authenticator: TOAuth2Authenticator;
  FSSLHandler: TIdSSLIOHandlerSocketOpenSSL;
  pingResponse: string;
begin
  Result := False;
  // 基础配置
  FBaseURL := 'https://www.the_portal_addresse.de';
  FAuthURL := 'https://auth.the_portal_addresse.de/auth/token';
  FClientID := 'Bla';
  FClientSecret := 'Bla';

  // 创建并配置SSL Handler,匹配原代码的SSL协议
  FSSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  FSSLHandler.SSLOptions.Method := sslvSSLv23;

  // 创建REST客户端并关联SSL Handler
  FRestClient := TRESTClient.Create(FBaseURL);
  FRestClient.IOHandler := FSSLHandler;
  FRestClient.ContentType := 'application/json';
  FRestClient.Accept := 'application/json';

  // 配置OAuth2客户端凭证模式
  FOAuth2Authenticator := TOAuth2Authenticator.Create(nil);
  FOAuth2Authenticator.GrantType := gtClientCredentials;
  FOAuth2Authenticator.ClientID := FClientID;
  FOAuth2Authenticator.ClientSecret := FClientSecret;
  FOAuth2Authenticator.TokenEndpoint := FAuthURL;
  FOAuth2Authenticator.SSLIOHandler := FSSLHandler; // 复用SSL配置

  // 关联认证器到客户端
  FRestClient.Authenticator := FOAuth2Authenticator;

  // 创建请求并调用ping接口
  FRestRequest := TRESTRequest.Create(nil);
  FRestRequest.Client := FRestClient;
  FRestRequest.Resource := '/system/ping';
  FRestRequest.Method := rmGET;

  try
    try
      // 执行请求(自动处理Token获取)
      FRestRequest.Execute;
      pingResponse := FRestRequest.Response.Content;
      if LowerCase(pingResponse) <> 'pong' then
        Exit;
      Result := True;
    except
      // 可根据需求添加异常处理逻辑
      Exit;
    end;
  finally
    // 释放资源
    FRestRequest.Free;
    FOAuth2Authenticator.Free;
    FRestClient.Free;
    FSSLHandler.Free;
  end;
end;

代码说明

  • SSL配置:手动创建TIdSSLIOHandlerSocketOpenSSL并指定sslvSSLv23,和原MVC代码的SSL设置完全一致,解决握手错误。
  • OAuth2认证:TOAuth2Authenticator的GrantType设为gtClientCredentials,自动处理client_credentials模式的Token请求,无需手动构造POST参数。
  • 请求执行:TRESTRequest会自动利用认证器获取并携带Bearer Token,无需手动管理Token的存储和添加。

替代方案:手动获取Token(如果不想用Authenticator组件)

如果你更倾向于手动模拟原代码的Token获取流程,也可以用TIdHTTP配合正确的SSL配置:

function ConnectionTest_ManualTokenFetch: Boolean;
var
  FBaseURL, FAuthURL, FClientID, FClientSecret, FAccessToken: string;
  FRestClient: TRESTClient;
  FRestRequest: TRESTRequest;
  FSSLHandler: TIdSSLIOHandlerSocketOpenSSL;
  http: TIdHTTP;
  ParameterList: TStringList;
  pingResponse: string;
begin
  Result := False;
  FBaseURL := 'https://www.the_portal_addresse.de';
  FAuthURL := 'https://auth.the_portal_addresse.de/auth/token';
  FClientID := 'Bla';
  FClientSecret := 'Bla';

  // 配置SSL Handler
  FSSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  FSSLHandler.SSLOptions.Method := sslvSSLv23;

  // 手动获取Token
  http := TIdHTTP.Create(nil);
  ParameterList := TStringList.Create;
  try
    http.IOHandler := FSSLHandler;
    http.HandleRedirects := False;
    http.Request.ContentType := CONTENTTYPE_APPLICATION_X_WWW_FORM_URLENCODED;
    http.Request.BasicAuthentication := False;

    ParameterList.Add('grant_type=client_credentials');
    ParameterList.Add('client_id=' + FClientID);
    ParameterList.Add('client_secret=' + FClientSecret);

    FAccessToken := http.Post(FAuthURL, ParameterList);
    FAccessToken := TJSONObject.ParseJSONValue(FAccessToken).GetValue<string>('access_token');
  except
    http.Free;
    ParameterList.Free;
    FSSLHandler.Free;
    Exit;
  end;
  http.Free;
  ParameterList.Free;

  // 创建REST客户端并设置Bearer Token
  FRestClient := TRESTClient.Create(FBaseURL);
  FRestClient.IOHandler := FSSLHandler;
  FRestClient.ContentType := 'application/json';
  FRestClient.Accept := 'application/json';
  FRestClient.AddAuthHeader('Bearer ' + FAccessToken);

  // 调用ping接口
  FRestRequest := TRESTRequest.Create(nil);
  FRestRequest.Client := FRestClient;
  FRestRequest.Resource := '/system/ping';
  FRestRequest.Method := rmGET;

  try
    try
      FRestRequest.Execute;
      pingResponse := FRestRequest.Response.Content;
      if LowerCase(pingResponse) <> 'pong' then
        Exit;
      Result := True;
    except
      Exit;
    end;
  finally
    FRestRequest.Free;
    FRestClient.Free;
    FSSLHandler.Free;
  end;
end;

内容的提问来源于stack exchange,提问作者Mahan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 01:47:51