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

Windows 11下Delphi Indy NTLM未使用指定用户名问题求助

解决Windows 11下Indy NTLM认证使用系统用户名而非指定用户名的问题

问题背景

基于Delphi Indy组件(已引入IdAuthenticationNTLM)的代码在Windows 10及更早版本运行正常,但Windows 11下失效。通过Fiddler抓包确认:NTLM协议发送的用户名是当前Windows系统用户名,而非代码中设置的MyUserName。相关代码如下:

procedure SetIdHTTPSSL(AIdHTTP: TIdHTTP);
var
  ssl: TIdSSLIOHandlerSocketOpenSSL;
begin
  ssl := TIdSSLIOHandlerSocketOpenSSL.Create(AIdHTTP);
  ssl.SSLOptions.SSLVersions := [sslvTLSv1_2];
  ssl.SSLOptions.Method := sslvTLSv1_2;
  ssl.SSLOptions.Mode := sslmUnassigned;
  ssl.OnVerifyPeer := SSLIOHandlerVerifyPeer;
  ssl.SSLOptions.VerifyMode := [sslvrfPeer];
  ssl.SSLOptions.VerifyDepth := 2;
  AIdHTTP.IOHandler := ssl;
end;

function IndyHttp(AFileName: string): Boolean;
var
  IdHTTP: TIdHTTP;
  tmpString: string;
  FileStrm: TFileStream;
begin
  IdHTTP := TIdHTTP.Create(Self);
  try
    IdHTTP.ProtocolVersion := pv1_1;
    IdHTTP.HTTPOptions := IdHTTP.HTTPOptions + [hoKeepOrigProtocol] + [hoInProcessAuth];
    IdHTTP.Request.Username := MyUserName;
    IdHTTP.Request.Password := MyPassword;
    IdHTTP.Request.BasicAuthentication := False;
    IdHTTP.Request.ContentType := 'application/octet-stream';
    IdHTTP.Request.CacheControl := 'no-cache';
    IdHTTP.Request.CustomHeaders.Add('Content-Location: ' + ExtractFileName(AFileName));
    IdHTTP.Request.UserAgent := '';
    IdHTTP.Request.Accept := '';

    SetIdHTTPSSL(IdHTTP);

    FileStrm := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite);
    try
      tmpString := IdHTTP.Post(GetHTTPString, FileStrm);
      Result := pos('OK', UpperCase(tmpString)) > 0;
    finally
      FileStrm.Free;
    end;
  finally
    IdHTTP.Free;
  end;
end;

原因分析

Windows 11下,Indy的NTLM认证默认会调用系统SSPI(Security Support Provider Interface)接口,而SSPI会优先使用当前登录用户的凭据,覆盖代码中手动设置的用户名和密码。这是由于Windows 11的SSPI行为调整,或是旧版本Indy对新系统兼容性不足导致的。

解决方案

1. 强制禁用NTLM的SSPI模式

遍历TIdHTTP的认证列表,找到TIdNTLM实例并设置UseSSPI := False,强制组件使用手动指定的凭据而非系统SSPI。修改IndyHttp函数如下:

function IndyHttp(AFileName: string): Boolean;
var
  IdHTTP: TIdHTTP;
  tmpString: string;
  FileStrm: TFileStream;
  Auth: TIdAuthentication; // 新增变量
begin
  IdHTTP := TIdHTTP.Create(Self);
  try
    IdHTTP.ProtocolVersion := pv1_1;
    IdHTTP.HTTPOptions := IdHTTP.HTTPOptions + [hoKeepOrigProtocol] + [hoInProcessAuth];
    IdHTTP.Request.Username := MyUserName;
    IdHTTP.Request.Password := MyPassword;
    IdHTTP.Request.BasicAuthentication := False;
    IdHTTP.Request.ContentType := 'application/octet-stream';
    IdHTTP.Request.CacheControl := 'no-cache';
    IdHTTP.Request.CustomHeaders.Add('Content-Location: ' + ExtractFileName(AFileName));
    IdHTTP.Request.UserAgent := '';
    IdHTTP.Request.Accept := '';

    // 新增:禁用NTLM的SSPI模式
    for Auth in IdHTTP.Authentications do
    begin
      if Auth is TIdNTLM then
      begin
        TIdNTLM(Auth).UseSSPI := False;
        Break;
      end;
    end;

    SetIdHTTPSSL(IdHTTP);

    FileStrm := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite);
    try
      tmpString := IdHTTP.Post(GetHTTPString, FileStrm);
      Result := pos('OK', UpperCase(tmpString)) > 0;
    finally
      FileStrm.Free;
    end;
  finally
    IdHTTP.Free;
  end;
end;

2. 确认hoInProcessAuth选项生效

代码中已添加hoInProcessAuth到HTTPOptions,该选项确保Indy自行处理认证流程,而非委托给系统。需确认此选项未被其他代码意外移除。

3. 升级Indy组件版本

若使用的是旧版Indy,建议升级到最新稳定版。新版本通常会修复Windows 11等新系统的兼容性问题,避免SSPI相关的行为冲突。

内容的提问来源于stack exchange,提问作者Hugues Van Landeghem

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:23:24