请谁能解释一下在下面的情况下发生了什么?是一个ISP重定向了一个URL,但另一个却没有重定向,还是发生了什么不同的事情?
我使用Delphi的TINetHttp(WinInet的一个封装器)登录到ISP上的cpanel并恢复会话代码。我利用TINetHttp的回调方法来获取重定向的URL,并从中提取会话代码。在一个ISP上,代码可以正常工作,但在另一个ISP上,回调给出的异常是 Error 12168 - The HTTP redirect request must be confirmed by the user
并将glboal var NewURL设置为空字符串。
假设登录的URL是 https://MyServer.net:2083/login/?user=username&pass=password
和INetHttp flNoAutoRedirect标志设置为FALSE,因此允许重定向。
var
NewURL : string;
url:= 'https://MyServer.net:2083/login/?user=username&pass=password'
RunWebPageCode(url, true); //navigate to the logon page, INetHttp callback sets NewURL to the redirected url
SessionID := ExtractBetween(NewURL , '/cpsess', '/frontend'); //get the session code from the redirected url
这里调用INetHttp回调,并将全局变量NewURL设置为重定向的URL(类似于https://MyServer.net:2083/cpsess1111633888/frontend/x3/index.html?login=1&post_login=9962390421682
),我从其中提取了来自于 /cpsess
和 /frontend
.
在不同的ISP上,使用几乎相同的(正确的)url,只是域名不同,INetHttp1 flNoAutoRedirect标志仍然设置为FALSE,INetHttp回调产生异常12168,NewURL被设置为空字符串。
然而,在这两个ISP中,如果我将flNoAutoRedirect标志设置为TRUE,这样INetHttp回调就不会被调用,我可以从我登陆的空白页面的html中提取会话ID,它将看起来像这样
<html><head><META HTTP-EQUIV="refresh"CONTENT="2;URL=/cpsess1796422993/frontend/paper_lantern/index.html login=1&post_login=99510958918744"></head><body></body></html>
所以下面的代码适用于两个ISP(如果flNoAutoRedirect标志设置为TRUE)。
url:= 'https://MyServer.net:2083/login/?user=username&pass=password'
RunWebPageCode(url, true); //navigate to the logon page
page := GetWebPageText(url, true); /get the html of the landing page
SessionID := ExtractBetween(page, '/cpsess', '/frontend');
下面是各种函数的完整代码,以备参考。
var
NewURL : string;
procedure Tjhm.RunWebPageCode(TheURL: string; secure: Boolean);
begin
try
try
if secure then
INetHttp1.Flags := INetHttp1.Flags + [flSecure]
else
INetHttp1.Flags := INetHttp1.Flags - [flSecure];
INetHttp1.Verb := vePost;
INetHttp1.Url := TheURL ;
INetHttp1.Open;
INetHttp1.OpenRequest;
INetHttp1.SendRequest;
except
on E : Exception do
begin
showmessage ('error running web page code +slinebreak
+ 'Exception class name = '+E.ClassName+ slinebreak
+ 'Exception message = '+E.Message);
end //on E
end;
finally
INetHttp1.Close;
end;
end;
procedure Tjhm.INetHttp1Callback(Sender: TObject; Status: Integer; Information: Pointer; InformationLength: Integer);
const
INTERNET_STATUS_REDIRECT = 110; //a constant in WinInet but redefined here for clarity
begin
if Status = INTERNET_STATUS_REDIRECT then //we have been redirected
begin
newURL := PAnsiChar(Information); // put new url into global var, typecast as 'Information' is a pointer to a non unicode char string
end;
end;
function Tjhm.ExtractBetween(const Value, A, B: string): string;
{utility to get the text between two delimiters}
var
aPos, bPos: Integer;
begin
result := '';
aPos := Pos(A, Value);
if aPos > 0 then begin
aPos := aPos + Length(A);
bPos := PosEx(B, Value, aPos);
if bPos > 0 then begin
result := Copy(Value, aPos, bPos - aPos);
end;
end;
end;
当一个POST请求返回307状态码时,WinInet不会进行自动重定向,而是返回错误12168。
所以我猜测你的第一个ISP返回的是旧的302代码,而另一个返回的是307。
请看 此处 获取完整的HTTP重定向代码列表。