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
相关产品推荐
相关产品推荐

