Delphi TWebBrowser - 如何使用登录名/密码代理?

时间:2017-04-19 07:34:14

标签: delphi proxy twebbrowser

我想将Delphi VCL组件TWebBrowser与代理一起使用。做这样的事情似乎很容易:

var PIInfo: PInternetProxyInfo;
begin
  PIInfo^.dwAccessType := INTERNET_OPEN_TYPE_PROXY;
  PIInfo^.lpszProxy := PAnsiChar('proxyserver.com:8888');
  PIInfo^.lpszProxyBypass := PAnsiChar('');
  UrlMkSetSessionOption(INTERNET_OPTION_PROXY, PIInfo, SizeOf(Internet_Proxy_Info), 0);
end;

但我也想使用代理进行身份验证。在这里我遇到了麻烦。我了解到可以使用WinAPI函数InternetSetOption设置代理名称和密码,如下所示:

var UserName: AnsiString;
    ConnectionHandle: HINTERNET;
begin
  // Init ConnectionHandle here 
  //... 
  res := InternetSetOption(ConnectionHandle, 
                           INTERNET_OPTION_PROXY_USERNAME,  
                           UserName, 
                           Length(UserName) + 1);
end;

我了解到使用INTERNET_OPTION_PROXY_USERNAME等参数的InternetSetOption只能应用于InternetConnect或HttpOpenRequest等函数生成的Internet句柄。

可以找到关于此问题的答案here

这不是问题,我可以先调用InternetConnect。但似乎不可能将此互联网句柄绑定到我的TWebBrowser。 TWebBrowser将忽略这些设置,因为它们适用于具体的专用互联网句柄。

所以我的问题是:是否可以在Delphi代码中使用身份验证设置代理以从TWebBrowser中使用它?

PS 即可。另一种选择是在TWebBrowser请求时记住登录/密码代理设置,但我有多次登录/密码,所以我想从代码中设置它们。

先谢谢你。

1 个答案:

答案 0 :(得分:0)

David Heffernan的评论迫使我走向正确的方向。回答我自己的问题,万一有人会在寻找答案,我找到了解决这个问题的三个方法。

所有代码段都可用于 Delphi XE4

<强> 1。在TWebBrowser中使用事件处理程序。

TWebBrowser有事件OnBeforeNavigate2。此方法的过程包含字段Headers。所以我们可以定义一些方法,如:

procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject; 
                                            const pDisp: IDispatch;
                                            const URL: OleVariant;
                                            const Flags: OleVariant;
                                            const TargetFrameName: OleVariant;
                                            const PostData: OleVariant;
                                            const Headers: OleVariant;
                                            var Cancel: WordBool);
var aHeaders: OleVariant;
begin
  if ASender = WebBrowser1 then begin
    if ALPos('X-StopHandling', Headers) <= 0 then begin
      aHeaders := Headers + 'Proxy-Authorization: BASIC BASE64_of_login_and_password' + #13#10 +
                            'X-StopHandling: 1' + #13#10;
      WebBrowser1.Navigate2(URL, Flags, TargetFrameName, PostData, aHeaders);
      Cancel := true;
    end;
  end;
end;

...并将其应用于WebBrowser ...

WebBrowser1.OnBeforeNavigate2 := WebBrowser1BeforeNavigate2;

此方法基于使用标头Proxy-Authorization,该标头允许为请求定义代理凭据。它还需要首先使用第一篇文章中定义的UrlMkSetSessionOption设置代理服务器和端口。

<强> 2。在方法Navigate2中使用headers参数

TWebBrowser的方法Navigate2支持参数Headers。因此,我们可以在调用此方法时定义相同的标头Proxy-Authorization。这种方式的问题是,Navigate2的所有内部调用(如果页面上的某些Javascript将通过AJAX调用某些内容)将没有此标题。

第一种解决方案没有这个缺点。

代码段在这里:

var EmptyParam: OleVariant;
    //...
begin

  // init proxy server and port first as described in the first post
  EmptyParam := System.Variants.EmptyParam;
  WebBrowser1.Navigate2('http://something', 
                        EmptyParam{Flags}, 
                        EmptyParam{TargetFrameName}, 
                        EmptyParam{PostData}, 
                        'Proxy-Authorization: ...' + #13#10);
end;

第3。使用替代组件

我发现了Delphi的Chromium实现(在积极开发中) - CEF4Delphi 。它基于 DCEF3 库,似乎有点遗留。

它支持开箱即用的代理设置界面。可以使用主浏览器对象的基本属性来定义代理服务器,端口,用户名和密码。

因此,如果使用TWebBrowser不一定是出于您的目的,您可以查看此组件。