问题描述
procedure TMain.WebServiceConnect(AContext:TIdContext);
Var
IP:String;
begin
try
IP:=AContext.Binding.PeerIP;
if Allowlist.IndexOf(IP)=-1 then Begin;
if Blocklist.IndexOf(IP)>-1 then Begin;
LogWrite('Blocking IP "'+IP+'"!',Detailed);
LogRequest(IP,'*BLOCKED*');
AContext.Connection.disconnect;
End;
End;
except
ON E:Exception do
LogWrite('"'+E.Message+'" while connection-check on blocklist',Detailed);
end;
end;
procedure TMain.WebServiceReceive(AContext:TIdContext; ARequestInfo:TIdHTTPRequestInfo; AResponseInfo:TIdHTTPResponseInfo);
begin
try
try
LogWrite('Handling connection from '+ARequestInfo.RemoteIP,Debug);
AResponseInfo.ResponseNo:=401;
ProcessWebRequest(AContext,ARequestInfo,AResponseInfo);
LogWrite('Closing connection to '+ARequestInfo.RemoteIP,Debug);
except
ON E:Exception do
LogWrite('"'+E.Message+'" while handling request!',verbose,FALSE);
End;
finally
End;
End;
但是我看到两个事件都是从被阻止的IP触发的!我做看到“被阻止的”日志行,但是看来AContext.Connection.disconnect
的作用不符合预期。
怎么了?
解决方法
如果OnCommand...
事件已关闭服务器的OnConnect
事件,则无法为给定的客户端连接触发该事件。在触发TIdRequestInfo
事件之前,服务器将无法读取客户端的请求数据以填充OnCommand...
对象。
因此,您可能没有像预期的那样实际致电Disconnect()
,或者是您误诊了该问题。
例如,在日志消息中,除了AContext.Binding.PeerPort
之外,还尝试包括AContext.Binding.Handle
甚至是PeerIP
,以确保日志消息实际上属于同一客户端连接。单独使用PeerIP
不足以唯一地标识单个连接。
也就是说,在极少数情况下Disconnect()
实际上没有关闭连接,您可以通过引发异常(例如通过SysUtils.Abort()
)来强制断开连接,以便服务器终止连接。调用线程并关闭套接字。
另外,谈到异常,您应该重新引发用except
捕获的任何异常(或者至少是从EIdException
派生的任何Indy异常),让服务器处理它。 / p>
尝试更多类似的方法:
procedure TMain.WebServiceConnect(AContext:TIdContext);
var
IP: String;
Port: TIdPort;
begin
try
IP := AContext.Binding.PeerIP;
Port := AContext.Binding.PeerPort;
if Allowlist.IndexOf(IP) = -1 then begin
if Blocklist.IndexOf(IP) > -1 then begin
LogWrite('Blocking IP "' + IP + ':' + IntToStr(Port) + '"!',Detailed);
LogRequest(IP,'*BLOCKED*');
AContext.Connection.Disconnect;
SysUtils.Abort;
end;
end;
except
on E: Exception do begin
if not (E is EAbort) then
LogWrite('"' + E.Message + '" while connection-check on blocklist',Detailed);
raise;
end;
end;
end;
procedure TMain.WebServiceReceive(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
IP: String;
Port: TIdPort;
begin
try
IP := AContext.Binding.PeerIP;
Port := AContext.Binding.PeerPort;
LogWrite('Handling connection from ' + IP + ':' + IntToStr(Port),Debug);
AResponseInfo.ResponseNo := 401;
ProcessWebRequest(AContext,ARequestInfo,AResponseInfo);
LogWrite('Closing connection to ' + IP + ':' + IntToStr(Port),Debug);
except
on E: Exception do begin
LogWrite('"' + E.Message + '" while handling request!',verbose,FALSE);
raise;
end;
end;
end;