我有一个在 IIS 下作为 ISAPI 扩展运行的 SOAP 服务器。对于身份验证,我决定使用 IIS 内置的基本身份验证。在 SOAP 服务器中,我只需要知道连接到 ISAPI 的用户的用户名。至于MSDN 文章:
在 IIS 处理请求之前,会执行客户端身份验证,以便设置执行请求的进程的安全上下文(或身份)。
我希望通过函数获取调用者的用户名GetUserName
。
这是 SOAP 服务器的实现代码:
TTestSOAP = class(TSOAPDataModule, ITestSOAP)
public
function WhoAmI: String; stdcall;
end;
function TTestSOAP.WhoAmI: String;
var
WinName: String;
BufSize: DWord;
Buffer: PWideChar;
begin
BufSize:= 1024;
Buffer:= AllocMem(BufSize);
try
if GetUserName(Buffer, BufSize) then
SetString(WinName, Buffer, BufSize)
else
RaiseLastOSError;
finally
FreeMem(Buffer);
end;
Result:= Format('You are: %s', [WinName]);
end;
ISAPI dll 使用 Delphi 2009 构建并使用 ISAPIThreadPool 单元。
通常一切正常,我得到正确的用户名。但是在重负载下,我得到了不匹配的结果。即:在客户端,我创建了连接到 SOAP 服务器的测试线程,循环调用 WhoAmI 函数 5 次并断开连接。运行三个或更多线程,每个线程都有不同的用户,WhoAmI 函数返回的用户名会随机交换。例如:作为“user1”连接的线程在 5 次调用中的一些(不是全部)中得到“你是:user2”。
有人知道这里发生了什么吗?您是否知道在客户端已通过 IIS 身份验证的 SOAPDataModule 中获取用户名的安全且正确的方法?
编辑:
做了更多的测试和调试:在 WhoAmI 函数实现中,我添加了这段代码LogonName:= GetSOAPWebModule.Request.GetFieldByName('AUTH_USER');
。它报告与 GetUserName 相同的用户名。似乎问题发生在客户端。所以关于客户端的一些细节: 提到的线程创建 HTTPRio 组件(每个线程都有自己的 HTTPRio)。对于授权,我设置了 Rio.HTTPWebNode.UserName 和 Rio.HTTPWebNode.Password。在 HTTPRio.HTTPWebNode.Connect(True) 之后,我确实在循环中调用了 ITestSOAP(HTTPRio).WhoAmI。
HTTPRio 背后的 Winet 是否可能与多个 HTTPRio 组件的用户名不匹配,每个组件都在不同的线程中运行,但是是同一个进程(应用程序)?