Delphi 登录名/密码无效的Indy TIdHTTP URI
我正在写一篇文章,以与特定的。该过程的一部分需要URI中的登录凭据,例如:Delphi 登录名/密码无效的Indy TIdHTTP URI,delphi,uri,url-encoding,indy10,Delphi,Uri,Url Encoding,Indy10,我正在写一篇文章,以与特定的。该过程的一部分需要URI中的登录凭据,例如: http://user:pass_with_#_sign@address:port/somespecificpath/ 我正在使用Indy的TIdHTTP.Get将请求发送到设备。但是,密码由“#”字符组成。如果使用普通密码将此URI放置在任何浏览器中,则#字符会将其丢弃。因此,我需要将密码的#编码为%23 http://user:pass_with_%23_sign@address:port/somespecific
http://user:pass_with_#_sign@address:port/somespecificpath/
我正在使用Indy的TIdHTTP.Get
将请求发送到设备。但是,密码由“#”字符组成。如果使用普通密码将此URI放置在任何浏览器中,则#
字符会将其丢弃。因此,我需要将密码的#
编码为%23
http://user:pass_with_%23_sign@address:port/somespecificpath/
当我将此URI粘贴到任何浏览器中时,它会成功登录并执行它所需的操作。但是,当我将完全相同的URI传递到TIdHTTP.Get
时,它不会成功登录,因此只要密码包含#
(或%23
),我就无法执行任何操作。将密码更改为不包含#
的解决方案太草率了。Indy一定是把这个URI/密码弄乱了
这是Indy中的一个bug,还是我还需要做些什么来让Indy接受这样一个编码密码
更新 我在其中一个摄像头上添加了一个新帐户,用户名和密码没有任何需要编码的特殊字符,身份验证仍然不起作用。似乎Indy完全从URI中剥离了登录凭据,甚至没有发送这些凭据。接下来我需要做的是监视实际发送的URI
更新2 我通过WireShark进行了数据包捕获,并验证了凭据
…用户:pass@...
甚至没有发送-它们从Indy实际发送的URI中剥离出来
更新3 TLama建议我在使用浏览器时捕获发送的内容。我尝试了这个,而且确信即使在使用浏览器时,捕获也不会显示这些登录凭据。。。即使它可以在浏览器中工作。因此,我必须找出另一种方法来确定是否发送了这些凭据
更新4 我尝试(在看到雷米的答案之前)在
Request.Username
和Request.Password
中提供这些凭证,而不是在URI中,但仍然没有成功。我不断从设备上得到“未经授权”的回复
更新5 除本段外,本节未提及与用户认证方式相关的内容: Grandstream视频监控API(应用程序编程接口)支持HTTP 1.0协议(RFC1945)。本文档通过支持的GET/POST方法详细解释了客户端函数的参数。用户需要管理员权限才能检索或设置参数 在这一点上,我确实将
TIdHTTP
协议版本切换到了1.0
更新6 希望最后的更新需要。。。我对浏览器(Chrome)和
TIdHTTP
之间的数据包捕获进行了另一次比较。Chrome实际上发送了两个请求,第一个请求没有任何凭据,但在第二个请求中,在标题Authorization:Basic…
和credentials:User:Pass
中有一个节点,而使用TIdHTTP
只发送一个没有这些凭据的请求
更新7 7是一个幸运数字:-)我刚刚意识到,我向设备发出的第一个请求返回“Unauthorized”,但我发出的所有后续请求(使用相同的
TIdHTTP
实例)都成功了!因此,回到我之前的更新,就像我在浏览器捕获中看到的一样,它需要第二次重复请求才能工作。#
是URL片段之前的URL中的非法字符,这就是为什么在URL的其他区域使用时必须将其编码为%23
用户名/密码实际上不是真实URL的一部分,这就是为什么当TIdHTTP
将URL发送到服务器时,用户名/密码会被剥离(监控任何web浏览器的流量,您将看到同样的情况发生)
要对TIdHTTP
使用HTTP身份验证,您需要使用TIdHTTP.Request.Username
和TIdHTTP.Request.Password
属性(并且不需要对值进行URL编码),例如:
如果您传递的URL中包含编码的用户名/密码,TIdHTTP
将去除这些值,并将它们移动到Request.username
和Request.password
属性中,但它们将保持原始编码格式,例如:
IdHTTP1.Get('http://user:pass_with_%23_sign@address:port/somespecificpath/')
// this will set Request.Username to 'user',
// Request.Password to 'pass_with_%23_sign', and
// send a request for 'http://address:port/somespecificpath/'
如果给您一个编码URL作为开始,您可以使用TIdURI
类在调用TIdHTTP.Get()
之前手动解码它,例如:
var
RequestUrl: string;
Uri: TIdURI;
begin
RequestUrl := 'http://user:pass_with_%23_sign@address:port/somespecificpath/';
...
Uri := TIdURI.Create(RequestURL);
try
IdHTTP1.Request.Username := TIdURI.URLDecode(Uri.UserName);
IdHTTP1.Request.Password := TIdURI.URLDecode(Uri.Password);
RequestURL := Uri.URI;
finally
Uri.Free;
end;
IdHTTP1.Get(RequestUrl);
...
end;
更新:无论哪种方式,请确保您拥有适当的IdAuthentication…
单元,或IdAllAuthentications
单元,在您的中,uses
子句启用Indy的HTTP身份验证类供TIdHTTP
使用。#
是URL中片段部分之前的URL中的非法字符,这就是为什么在URL的其他区域使用时必须将其编码为%23
用户名/密码实际上不是真实URL的一部分,这就是为什么当TIdHTTP
将URL发送到服务器时,用户名/密码会被剥离(监控任何web浏览器的流量,您将看到同样的情况发生)
要对TIdHTTP
使用HTTP身份验证,您需要使用TIdHTTP.Request.Username
和TIdHTTP.Request.Password
属性(并且不需要对值进行URL编码),例如:
如果您传递的URL中包含编码的用户名/密码,TIdHTTP
将去除这些值,并将它们移动到Request.username
和Request.password
var
RequestUrl: string;
Uri: TIdURI;
begin
RequestUrl := 'http://user:pass_with_%23_sign@address:port/somespecificpath/';
...
Uri := TIdURI.Create(RequestURL);
try
IdHTTP1.Request.Username := TIdURI.URLDecode(Uri.UserName);
IdHTTP1.Request.Password := TIdURI.URLDecode(Uri.Password);
RequestURL := Uri.URI;
finally
Uri.Free;
end;
IdHTTP1.Get(RequestUrl);
...
end;
FWeb.Get(U);
FWeb.Get(U, R);