如何在WinInet中为HTTPS验证代理服务器?

时间:2018-01-11 01:19:36

标签: delphi authentication https proxy wininet

根据微软支持:How To Handle Proxy Authorization with WinInet 和其他Delphi示例(http://forum.codecall.net/topic/51366-internetopen-tthreads-maxconnectionsperserver/https://pastebin.com/f1ea3a752),我编写了以下测试代码,尝试通过经过身份验证的代理服务器访问https页面的正确方法:

program Project35;

{$APPTYPE CONSOLE}

uses
  SysUtils, WinInet, Windows, Classes;

Function sslGet(Const AServer, AUrl : string): AnsiString;
var
  aBuffer     : Array[0..4096] of Char;
  BufStream   : TMemoryStream;
  sMethod     : AnsiString;
  BytesRead   : Cardinal;
  pSession    : HINTERNET;
  pConnection : HINTERNET;
  pRequest    : HINTERNET;
  LUsername: string;
  LPassword: string;
  LProxy, LBypass: string;
  LAgent: string;
  LStatusCode, LStatusLen, LIndex : DWORD;
begin
  Result := '';
  LUsername := 'User-002' ;
  LPassword := 'test2';
  LProxy := 'myproxyserver:808';//https=https://
  LBypass := '<local>';
  LAgent := 'Bo-Test';
//pSession := InternetOpen(PChar(LAgent), INTERNET_OPEN_TYPE_DIRECT, nil, nil, 0);
  pSession := InternetOpen(PChar(LAgent), INTERNET_OPEN_TYPE_PROXY , PChar(LProxy), PChar(LBypass), 0);
//pSession := InternetOpen(PChar(LAgent), INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY , nil,  nil, 0);

  if Assigned(pSession) then
  try

//    pConnection := InternetConnect(pSession, PChar(AServer), INTERNET_DEFAULT_HTTPS_PORT, PChar(LUsername), PChar(LPassword), INTERNET_SERVICE_HTTP, 0, 0);
  pConnection := InternetConnect(pSession, PChar(AServer), INTERNET_DEFAULT_HTTPS_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);

    if Assigned(pConnection) then
    try

      sMethod := 'GET';
      pRequest := HTTPOpenRequest(pConnection, PChar(sMethod), PChar(AURL), nil, nil, nil,
                    INTERNET_FLAG_SECURE or
                    INTERNET_FLAG_KEEP_CONNECTION or
                    INTERNET_FLAG_NO_CACHE_WRITE or
                    INTERNET_FLAG_PRAGMA_NOCACHE or
                    INTERNET_FLAG_NO_AUTH or
                    INTERNET_FLAG_IGNORE_CERT_CN_INVALID or
                    INTERNET_FLAG_IGNORE_CERT_DATE_INVALID or
                    INTERNET_FLAG_NO_UI or
                    INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS or
                    SECURITY_FLAG_IGNORE_UNKNOWN_CA, 0); //or INTERNET_FLAG_NO_AUTH

      if Assigned(pRequest) then
      try

        if HTTPSendRequest(pRequest, nil,  0, nil, 0) then
        begin
          LStatusLen := SizeOf(LStatusCode);
          LIndex := 0;
          // expecting a 407 returned
          HttpQueryInfo(pRequest, HTTP_QUERY_STATUS_CODE or HTTP_QUERY_FLAG_NUMBER,
          @LStatusCode, LStatusLen, LIndex);
          Write('Status code=');
          writeln(LStatusCode);

          // resend after 407
          InternetSetOption(pRequest, INTERNET_OPTION_PROXY_USERNAME, PChar(LUsername) , length(LUsername));
          InternetSetOption(pRequest, INTERNET_OPTION_PROXY_PASSWORD, PChar(LPassword), length(LPassword));
          HTTPSendRequest(pRequest, nil,  0, nil, 0);
          HttpQueryInfo(pRequest, HTTP_QUERY_STATUS_CODE or HTTP_QUERY_FLAG_NUMBER,
          @LStatusCode, LStatusLen, LIndex);
          Write('Resend status code=');
          writeln(LStatusCode);

          BufStream := TMemoryStream.Create;
          try

           while InternetReadFile(pRequest, @aBuffer, SizeOf(aBuffer), BytesRead) do
             begin
               if (BytesRead = 0) then Break;

               BufStream.Write(aBuffer, BytesRead);
             end;

             aBuffer[0] := #0;
             BufStream.Write(aBuffer, 1);
             Result := PChar(BufStream.Memory);

          finally
           FreeAndNil(BufStream);
          end;
        end
        else begin
          Writeln(GetLastError());
        end;

      finally
        InternetCloseHandle(pRequest);
      end;

    finally
      InternetCloseHandle(pConnection);
    end;

  finally
    InternetCloseHandle(pSession);
  end;
end;

var
  StopEnter: string;
begin
  try
    // the wsdl is only available with ssl, i.e., https://services.staging.referralnet.com.au/services/Referral_Service_51?wsdl
    // it is invalid for http://services.staging.referralnet.com.au/services/Referral_Service_51?wsdl
    Writeln(sslGet('services.staging.referralnet.com.au', '/services/Referral_Service_51?wsdl'));
    Write('Press Enter to stop ...');
    Readln(StopEnter);
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

我使用CCProxy作为此测试的代理服务器。 我尝试使用两台机器,一台修改了hosts文件,以便wsdl页面的服务器指向127.0.0.1,另一台修改了防火墙,因此阻止了服务器的所有流量。

两次测试都返回了两个407代码,即原始和重发请求均以407失败。

可能有什么不对?或者有人能指出我一个有效的例子吗?

1 个答案:

答案 0 :(得分:0)

看看THttpRIo组件如何处理这个问题。只需按照代码中的代理属性使用即可。