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

RAD Server 10.3.1 64位编译下TEMSClientAPI认证失败求助

问题背景与故障现象
  • 基于Delphi 10.3.1开发的RAD Server Web应用,原32位部署运行正常,近期编译为64位部署至Windows Server的Apache后,多数功能正常,但Rest.Backend.EMSApi.TEMSClientAPI认证流程失败
  • 核心故障点:执行代码LEMSClientAPI.QueryUserName(LAgency + '.' + LUserName, LUser)时触发错误
  • 对比验证:在EMSDevServer(未加密环境)中运行时认证完全正常;Apache配置无明显问题,已认证用户可正常访问非认证端点
  • 初步疑点:查阅资料提示可能存在TLS版本不匹配,但不清楚如何针对Delphi组件开展排查
相关代码
procedure TCustomLogonResource.PostLogin(const AContext: TEndpointContext;
  const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  LEMSAPI       : TEMSInternalAPI;
  LEMSClientAPI : Rest.Backend.EMSApi.TEMSClientAPI;
  LResponse     : IEMSResourceResponseContent;
  LValue        : TJSONValue;
  LUserName     : string;
  LPassword     : string;
  ObjCons       : TJSONObject;
  ObjID         : String;
  LUser         : REST.Backend.EMSApi.TEMSClientAPI.TUser;
  LLogin        : REST.Backend.EMSApi.TEMSClientAPI.TLogin;
  LAgency       : String;
  myJSON        : TJSONObject;
  myUsers       : TArray<string>;
  ARec          : TEMSClientAPI.TUpdatedAt;
  AInfo         : TEMSClientAPI.TConnectionInfo;
  LEID          : String;
  LFullName     : String;
  LProfile      : String;
  LModuleName   : String;
  LToken        : String;
  iPos          : Integer;
  LOTP          : String;
  LOTU          : String;
  sList: TStringList;
  tempJSONArray: TJSONArray;
  tempJSONValue: TJSONValue;
  tempJSONObject: TJSONObject;
  tempStream: TStream;
  i: Integer;
  slDiag: TStringList;
begin
  ObjCons := nil;
  tempJSONArray := nil;
  slDiag := nil;
  LModuleName := '';
  LToken  := '';
  iPos := 0;
  LOTP := '';
  LOTU := '';
  myJSON := TJSONObject.Create;
  // Create in-process EMS API
  LEMSAPI := TEMSInternalAPI.Create(AContext);
  AInfo.BaseURL := 'https://www.notmyrealurl.com/api/';
  AInfo.MasterSecret := '**************';
  LEMSClientAPI := Rest.Backend.EMSApi.TEMSClientAPI.Create();
  LEMSClientAPI.ConnectionInfo := AInfo;
  LEMSClientAPI.Authentication := REST.Backend.EMSApi.TEMSClientAPI.TAuthentication.MasterSecret;
  try
    Try
      // Extract credentials from request
      if not (ARequest.Body.TryGetValue(LValue) and
        LValue.TryGetValue<string>(TEMSInternalAPI.TJSONNames.UserName, LUserName) and
        LValue.TryGetValue<string>(TEMSInternalAPI.TJSONNames.Password, LPassword))
      then
        AResponse.RaiseBadRequest('', 'Missing credentials')
      LAgency := ANSILowerCase(Trim(LeftStr(LUserName, Pos('.', LUserName) - 1)));

      ARequest.Body.TryGetObject(tempJSONObject);
      tempJSONObject.TryGetValue<string>('module_name', LModuleName);
      tempJSONObject.TryGetValue<string>('otu', LOTU);
      tempJSONObject.TryGetValue<string>('otp', LOTP);

      // if the username are valid user in the Agency's Users Table in their Agency DB, then proceed
      if ValidateCredentials('', LPassword, LModuleName, LOTU, LOTP, LUserName, LEID, LFullName, LProfile, LToken) then
      begin
        // if not using OTP/OTU
        if LOTU = '' then
        begin
          sPlace := 'Before LEMSClientAPI';

          // if the user doesn't exist in the EMS database, we need to add him
          if not LEMSClientAPI.QueryUserName(LAgency + '.' + LUserName, LUser) then
          begin
            LEMSClientAPI.SignupUser(LAgency + '.' + LUserName,LPassword,nil,LLogin);
          end
          // if the user already exists in the EMS database
          else
          begin
            ObjId := LUser.UserID;
            ObjCons := TJSONObject.Create;
            ObjCons.AddPair('password', LPassword);
            LEMSClientAPI.UpdateUser(LUser,ObjCons,ARec);
          end;
        end; // end if not using OTU/OTP

        if LToken = '' then
        begin
          LResponse := LEMSAPI.LoginUser(LAgency + '.' + LUserName, LPassword);
          LEMSClientAPI.LoginUser(LAgency + '.' + LUserName,LPassword, LLogin);
          UpdateSessionToken(LAgency + '.' + LUserName,LLogin.AuthToken);
        end;

        iPos := Pos('.', LUserName);
        myJSON.AddPair('agency_key',LAgency);
        myJSON.AddPair('user',LUserName);
        myJSON.AddPair('username',LAgency + '.' + LUserName);
        myJSON.AddPair('eid',LEID);
        myJSON.AddPair('fullname',Trim(LFullName));
        myJSON.AddPair('profile',Trim(LProfile));
        myJSON.AddPair('sessionToken',IfThen(LToken = '', LLogin.AuthToken, LToken));
        myJSON.AddPair('module_name ',LModuleName);
        
        AResponse.StatusCode := 200;
      end
      else
      begin
        myJSON.AddPair('module_name',LModuleName);
        myJSON.AddPair('Authentication Failed','Invalid username or password');

        AResponse.StatusCode := 400;
      end;
    except
      on e: exception do
      begin
        raise Exception.Create(e.Message);
      end;
    end;
  finally
    AResponse.Body.SetValue(myJSON,true);
    LEMSAPI.Free;
    ObjCons.Free;
    slDiag.Free;
  end;
end;
排查思路与建议
  • 捕获精准错误信息:当前代码仅重新抛出异常消息,建议在except块中添加日志记录,输出LEMSClientAPI.LastError的完整内容(包括错误码、响应内容),同时记录异常的StackTrace,明确是连接失败、认证失败还是API逻辑错误
  • 强制指定TLS版本:
    • Delphi 10.3.1的HTTP客户端默认依赖Windows SCHANNEL,64位环境下需确保Apache支持TLS 1.2及以上版本
    • 显式配置TLS版本:通过LEMSClientAPI.HTTPClient.SSLOptions.SSLVersions := [TSSLVersion.TLSv1_2, TSSLVersion.TLSv1_3];强制客户端使用高版本TLS,避免版本不匹配
  • 验证服务端连通性:
    • 用curl或Postman直接调用AInfo.BaseURL对应的/users接口,携带MasterSecret认证(请求头添加X-EMS-MasterSecret: [你的密钥]),确认服务端可正常响应
    • 检查AInfo.BaseURL是否正确,64位部署后RAD Server的API端点是否有端口、路径变更
  • 排查64位环境依赖:
    • 确认Windows Server已安装Delphi 10.3.1的64位运行时库,以及RAD Server所需的64位组件(如Indy、REST组件)
    • 检查Apache反向代理配置:是否正确转发HTTPS请求到RAD Server的64位服务端口,是否存在请求头丢失(如Host、X-Forwarded-Proto)的情况
  • 对比进程内API与远程API差异:
    • 代码中同时使用了TEMSInternalAPI(进程内调用)和TEMSClientAPI(远程调用),尝试用TEMSInternalAPI替代TEMSClientAPI执行QueryUserName操作,若成功则说明问题出在远程调用链路,而非用户逻辑
  • 验证用户名字符处理:
    • 检查LAgency + '.' + LUserName拼接后的用户名在64位环境下的字符编码是否与32位一致(比如ANSI转UTF-8是否存在问题),可尝试用硬编码的测试用户名调用QueryUserName,排除字符处理导致的错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 20:24:52