2012-03-25 6 views
1

J'ai un robot d'exploration pour HTTP qui passe à Wininet.Wininet SSL client authentifier l'étrangeté

Cela fonctionne généralement bien, mais pour un site Web, j'obtiens l'erreur ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED

code Exemple:

vErrorNone := HttpSendRequest(HttpOpen_Request, nil, 0, nil, 0); 
if vErrorNone = False then 
    begin 
    vErrorID := GetLastError; 
    if (vErrorID = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED) then 
     begin 
     // this error 
     end 
    ; 
    end 
; 

J'ai ensuite essayé une expérience avec:

 TmpFakePointer := nil; 
     vErrorNone := 
     InternetErrorDlg(
      GetDesktopWindow() 
      , 
      HttpOpen_Request 
      , 
      ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED 
      , 
      0 
      or FLAGS_ERROR_UI_FILTER_FOR_ERRORS 
      or FLAGS_ERROR_UI_FLAGS_GENERATE_DATA 
      or FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS 
      , 
      TmpFakePointer 
     ) 
     = ERROR_SUCCESS 
     ; 
     if vErrorNone then 
     begin 
      vErrorNone := HttpSendRequest(HttpOpen_Request, nil, 0, nil, 0); 
     end 
     ; 

Cependant, deux choses sont impairs ici:

  • 1) Aucune boîte de dialogue affiche
  • 2) Il fonctionne
  • 2.1) Pas d'erreur sur le deuxième HttpSendRequest
  • 2.2) Les données valides sont retournés

Il trouve ci-dessus combinaison très étrange et contraire à la documentation. Puisque l'utilisateur n'a sélectionné aucun certificat, pourquoi cela fonctionne-t-il? Si Wininet revient au certificat d'authentification anonyme du client lorsque la boîte de dialogue ne peut pas être affichée (je suppose que je lui ai donné un handle incorrect pour afficher la boîte de dialogue? sans l'appel à InternetErrorDlg?

Répondre

2

bien

Il y a deux choses que vous pouvez faire:

1: Voir l'erreur de certificat à l'utilisateur et lui laisser décider de poursuivre ou non.
2: Ignorez les erreurs de certificat que vous obtenez.

Je suis spectacle va vous expliquer comment faire la deuxième option:

Lorsque vous obtenez le ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED ou toute autre erreur de certificat, vous devez appeler InternetSetOptions dire wininet qu'il devrait ignorer l'erreur et continuer. Après cela, vous devez renvoyer la demande.

function SetToIgnoreCerticateErrors(var aErrorMsg: string): Boolean; 
var 
    vDWFlags: DWord; 
    vDWFlagsLen: DWord; 
begin 
    Result := False; 
    try 
    vDWFlagsLen := SizeOf(vDWFlags); 
    if not InternetQueryOptionA(oRequestHandle, INTERNET_OPTION_SECURITY_FLAGS, @vDWFlags, vDWFlagsLen) then begin 
     aErrorMsg := 'Internal error in SetToIgnoreCerticateErrors when trying to get wininet flags.' + GetWininetError; 
     Exit; 
    end; 
    vDWFlags := vDWFlags or SECURITY_FLAG_IGNORE_UNKNOWN_CA or SECURITY_FLAG_IGNORE_CERT_DATE_INVALID or SECURITY_FLAG_IGNORE_CERT_CN_INVALID or SECURITY_FLAG_IGNORE_REVOCATION; 
    if not InternetSetOptionA(oRequestHandle, INTERNET_OPTION_SECURITY_FLAGS, @vDWFlags, vDWFlagsLen) then begin 
     aErrorMsg := 'Internal error in SetToIgnoreCerticateErrors when trying to set wininet INTERNET_OPTION_SECURITY_FLAGS flag .' + GetWininetError; 
     Exit; 
    end; 
    Result := True; 
    except 
    on E: Exception do begin 
     aErrorMsg := 'Unknown error in SetToIgnoreCerticateErrors.' + E.Message; 
    end; 
    end; 
end; 


vErrorNone := HttpSendRequest(HttpOpen_Request, nil, 0, nil, 0); 
if vErrorNone = False then 
    begin 
    vErrorID := GetLastError; 
    if (vErrorID = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED) then 
    begin 
     //call SetToIgnoreCerticateErrors 
     //re-send the request 
    end 
    end 
end; 

J'ai extrait le SetToIgnoreCerticateErrors de mon API WinInet et il ne peut pas compiler exactement comment il est.

Ce sont les étapes:

1 - Obtenir l'erreur
2 - Vérifiez si l'erreur est une erreur de certificat
3 - Si elle est une erreur de certificat, appelez InternetSetOption comme je l'ai fait.
4 - Renvoyer la demande.

Je ne sais pas comment implémenter la première option "Afficher l'erreur de certificat à l'utilisateur et lui laisser décider ou ne pas continuer." parce que je n'ai jamais eu à le faire.

En outre, vérifier cela: How To Handle Invalid Certificate Authority Error with WinInet

J'espère que cela vous aide.

+0

Merci, je vais essayer!:) Je trouve toujours bizarre que ma solution fonctionne car elle est contraire à la documentation. Je vais passer à la vôtre :) – Tom

+0

Juste testé la solution, et ça marche! Merci :) – Tom

+0

Je suis heureux de pouvoir vous aider. –