Authentification mutuelle Delphi

J'utilise la bibliothèque WinINet pour me connecter à un site web.

en utilisant Internet Explorer (Win10) cela fonctionne et me montre le message pour sélectionner le certificat à utiliser.

voici le code delphi que j'appelle:

FUNCTION TRAD.lastOrganization(): Integer;
VAR
  js:TlkJSONobject;
  ws: TlkJSONstring;
  url, resp: String;
  count,statusCodeLen, bodyCodeLen: Cardinal;
  header,tmp: String;
  buffer, body: String;
  statusCode: ARRAY [0 .. 1024] OF Char;
  bodyCode: ARRAY [0 .. 1024] OF Char;
  UrlHandle: HINTERNET;
BEGIN
  buffer := '00000000000000000000';
  url := contextUrl + '/rest/organization/count';
  UrlHandle := InternetOpenUrl(NetHandle, PChar(url), nil, 0, INTERNET_FLAG_RELOAD, 0);
  IF NOT ASSIGNED(UrlHandle) THEN
    SHOWMESSAGE('Unable to read the amount of Organization using the URL ' + url + ': ' +  SysErrorMessage(GetLastError));
  statusCodeLen := Length(statusCode);
  bodyCodeLen := Length(bodyCode);
  count := 0;
  IF HttpQueryInfo(UrlHandle, HTTP_QUERY_STATUS_CODE, @statusCode[0], statusCodeLen, count) THEN
  BEGIN
    buffer := statusCode;
    IF buffer <> '200' THEN
    BEGIN
      ShowMessage('While read amount of Organization I got a status code ' + buffer + ' but 200 was expected.');
      EXIT;
    END;
  END;

  count := 0;
  body := '';
  REPEAT
    FillChar(bodyCode, bodyCodeLen, 0);
    IF NOT InternetReadFile(UrlHandle, @bodyCode[0], bodyCodeLen, count) THEN
    BEGIN
      ShowMessage('Problem on reading from response stream while read the amount of Organization using the URL ' + url + '.');
      EXIT;
    END;
    IF count > 0 THEN
    BEGIN
      tmp := bodyCode;
      body := body + LeftStr(tmp, count);
    END;
  UNTIL count = 0;

  InternetCloseHandle(UrlHandle);
  Result := strtoint(body);
END;

si j'appelle la méthode, je reçois ce message:

enter image description here

Buuut, en utilisant le bord-Browser je dois spécifier un certificat, et il fonctionne juste grand.

enter image description here

Question

Comment spécifier le certificat?

Edit (nouvelles informations):

si je change le code en

FUNCTION TRAD.lastOrganization(): Integer;
VAR
  js:TlkJSONobject;
  ws: TlkJSONstring;
  url, resp: String;
  count,statusCodeLen, bodyCodeLen: Cardinal;
  header,tmp: String;
  buffer, body: String;
  statusCode: ARRAY [0 .. 1024] OF Char;
  bodyCode: ARRAY [0 .. 1024] OF Char;
  UrlHandle: HINTERNET;
BEGIN
  buffer := '00000000000000000000';
  url := contextUrl + '/rest/organization/count';
  UrlHandle := InternetOpenUrl(NetHandle, PChar(url), nil, 0, INTERNET_FLAG_RELOAD, 0);
  IF NOT ASSIGNED(UrlHandle) THEN
    raiseLastOSError();

Il affiche: enter image description here

18
demandé sur Peter Rader 2018-03-23 21:57:57

2 réponses

Envisager l'utilisation de InternetErrorDlg

exemple de Code:

function WebSiteConnect(const UserAgent: string; const Server: string; const Resource: string;): string;
var
  hInet: HINTERNET;
  hConn: HINTERNET;
  hReq:  HINTERNET;
  dwLastError:DWORD;

  nilptr:Pointer;
  dwRetVal:DWORD;

  bLoop: boolean;
  port:Integer;
begin
  hInet := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if hInet = nil then exit;
  hConn := InternetConnect(hInet, PChar(Server), INTERNET_DEFAULT_HTTPS_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);
  if hConn = nil then
  begin
    InternetCloseHandle(hInet);
    exit;
  end;
  hReq := HttpOpenRequest(hConn, 'GET', PChar(Resource), 'HTTP/1.0', nil, nil, INTERNET_FLAG_SECURE, 0);
  if hReq = nil then
  Begin
    InternetCloseHandle(hConn);
    InternetCloseHandle(hInet);
    exit;
  end;

  bLoop := true;
  while bLoop do
  begin
    if HttpSendRequest(hReq, nil, 0, nil, 0) then
      dwLastError := ERROR_SUCCESS
    else
      dwLastError:= GetLastError();

    if dwLastError = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED then
    begin
      dwRetVal:= InternetErrorDlg(application.handle, hReq, dwLastError,
      FLAGS_ERROR_UI_FILTER_FOR_ERRORS or
      FLAGS_ERROR_UI_FLAGS_GENERATE_DATA or
      FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
      nilptr );

      if dwRetVal = ERROR_INTERNET_FORCE_RETRY then
        continue
      else  // CANCEL button
      begin
        InternetCloseHandle(hReq);
        InternetCloseHandle(hConn);
        InternetCloseHandle(hInet);
        exit;
      end;
    end
    else
      bLoop := false;
  end;
  Result:= ...
end;
4
répondu vzamanillo 2018-04-22 09:14:54

en utilisant WinHTTP (vous pouvez faire la même chose avec WinInetHTTP) vous pouvez définir le certificat comme ceci via ActiveX:

// Instantiate a WinHttpRequest object.
var HttpReq = new ActiveXObject("WinHttp.WinHttpRequest.5.1");

// Open an HTTP connection.
HttpReq.Open("GET", "https://www.fabrikam.com/", false);

// Select a client certificate.
HttpReq.SetClientCertificate(
            "LOCAL_MACHINE\Personal\My Middle-Tier Certificate");

// Send the HTTP Request.
HttpReq.Send();

donc C'est facile avec ActiveX mais ce n'est pas vraiment ce que vous voulez (je vous ai donné l'exemple comme illustration). Ainsi, avec l'API windows, WinHTTP vous permet de sélectionner et d'envoyer un certificat depuis un magasin de certificats local. L'exemple de code suivant montre comment ouvrir un magasin de certificats et localiser un certificat basé sur le nom du sujet après le ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED error has been returned.

if( !WinHttpReceiveResponse( hRequest, NULL ) )
  {
    if( GetLastError( ) == ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED )
    {
      //MY is the store the certificate is in.
      hMyStore = CertOpenSystemStore( 0, TEXT("MY") );
      if( hMyStore )
      {
        pCertContext = CertFindCertificateInStore( hMyStore,
             X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
             0,
             CERT_FIND_SUBJECT_STR,
             (LPVOID) szCertName, //Subject string in the certificate.
             NULL );
        if( pCertContext )
        {
          WinHttpSetOption( hRequest, 
                            WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
                            (LPVOID) pCertContext, 
                            sizeof(CERT_CONTEXT) );
          CertFreeCertificateContext( pCertContext );
        }
        CertCloseStore( hMyStore, 0 );

        // NOTE: Application should now resend the request.
      }
    }
  }
2
répondu loki 2018-04-01 14:49:49