2017-05-02 5 views
2

Der folgende Code fordert ein OAuth2-Token an. Es funktioniert mit Indy 10.0.52, aber mit Indy 10 SVN 5412 erzeugt es einen 400 Bad Request Fehler aufgrund ungültiger Anfrage Anmeldeinformationen.Codierungsprobleme nach Indy-Upgrade

Ich habe Code hinzugefügt, um IdLogFile Datum zu erfassen. Das Protokoll der Version Indy 10.0.52 enthält die folgende Zeile mit den Anmeldeinformationen.

Sent 05/01/2017 18:34:35: grant_type=password&username=*************_*****-*****&password=***}%25**(**(*** 

Aus Sicherheitsgründen habe ich alle alphanumerischen Zeichen durch '*' ersetzt. Die Zeichen "% 25" waren ursprünglich ein "%" im tatsächlichen Kennwort. Etwas hat das ursprüngliche "%" in "% 25" übersetzt, aber nichts an den anderen Sonderzeichen geändert.

Bei der ersten Überprüfung des Protokolls vom Indy 10 SVN 5412 wurde eine Nachricht vom Server festgestellt, die auf ungültige Anmeldeinformationen hinweist. Außerdem zeigten alle Sonderzeichen in der Zeile, die der obigen Zeile entsprach, dass alle Sonderzeichen codiert waren. Der grant_type, der Benutzername und das Passwort wurden mit einer tStringList gerendert, die im Urlencoding gefunden wurde. Ich habe den Code so geändert, dass dieselben Daten mit einem Stream gerendert werden und jetzt nichts mehr codiert wird. nicht einmal die "%" wird in "% 25" übersetzt, und ich bekomme weiterhin die ungültige Anmeldeinformationen Nachricht.

Also meine Fragen sind, warum würde Indy 10.0.52 nur das "%" Zeichen in "% 25" übersetzen und wie kann ich dieses Verhalten in Indy 10 SVN 5412 replizieren?

Folgendes ist das vollständige Protokoll von der Indy 10.0.52 Version, die funktioniert.

Stat Connected. 
Sent 05/01/2017 18:34:35: POST /auth/realms/hvac/tokens/grants/access HTTP/1.0<EOL>Content-Type: application/x-www-form-urlencoded; charset="utf-8"<EOL>Content-Length: 82<EOL>Authorization: Basic<EOL> **********<EOL>Host: services.ccs.utc.com:443<EOL>Accept: text/html, */*<EOL>Accept-Encoding: identity<EOL>User-Agent: Mozilla/4.0 (compatible; MSIE 8.0)<EOL><EOL> 
Sent 05/01/2017 18:34:35: grant_type=password&username=*************_*****-*****&password=***}**%25**(**(*** 
Recv 05/01/2017 18:34:35: HTTP/1.1 200 OK<EOL>Server: Apache-Coyote/1.1<EOL>Pragma: no-cache<EOL>Cache-Control: no-store<EOL>Content-Type: application/json;charset=UTF-8<EOL>Content-Length: 569<EOL>Date: Mon, 01 May 2017 22:34:35 GMT<EOL>Connection: close<EOL><EOL>{<EOL> "access_token":"**********",<EOL> "token_type":"Bearer",<EOL> "expires_in":1800,<EOL> "refresh_token":"**********",<EOL> "id_token":"**********"<EOL>} 
Stat Disconnected. 
Stat Disconnected 

Im Folgenden ist das vollständige Protokoll von der Indy 10 SVN 5412-Version, die mit ungültigen Anmeldeinformationen fehlschlägt.

Stat Connected. 
Sent 05/02/2017 15:11:08: POST /auth/realms/hvac/tokens/grants/access HTTP/1.0<EOL>Connection: keep-alive<EOL>Content-Type: application/x-www-form-urlencoded; charset=utf-8<EOL>Content-Length: 82<EOL>Authorization: Basic **********<EOL>Host: services.ccs.utc.com<EOL>Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8<EOL>User-Agent: Mozilla/3.0 (compatible; Indy Library)<EOL><EOL> 
Sent 05/02/2017 15:11:08: grant_type=password&username=*************_*****-*****&password=***}**%**(**(***<EOL> 
Recv 05/02/2017 15:11:08: HTTP/1.1 400 Bad Request<EOL>Server: Apache-Coyote/1.1<EOL>Content-Type: application/json;charset=UTF-8<EOL>Content-Length: 84<EOL>Date: Tue, 02 May 2017 19:11:08 GMT<EOL>Connection: close<EOL><EOL>{<LF> "error": "invalid_grant",<LF> "error_description": "Invalid request credentials"<LF>} 
Stat Disconnected. 
Stat Disconnected. 

Antwort

4

Sie veröffentlichen eine TMemoryStream, die geschrieben wird wie sie ist, TIdHTTP nicht codiert es nicht in irgendeiner Weise in jeder Version von Indy. Sie sind dafür verantwortlich, dass der Inhalt Ihrer TMemoryStream korrekt formatiert ist. Das ist bei dir, nicht bei Indy.

TIdHTTP.Post() hat eine Überlastung, die Beiträge ein TStrings anstelle eines TStream, Formatierung die Saiten in application/x-www-webform-urlencoded Format für Sie. Sie müssen keinen TMemoryStream überhaupt verwenden.

In Indy 10.0.52, TIdHTTP.Post(TStrings) codiert nur die value von name=value Paare und codiert sie es TIdURI.ParamsEncode() verwenden, die alle Zeichen Prozent-kodiert, das in der Menge zwischen #33..#128, inclusive '*#%<> []' oder nicht ein ASCII-Zeichen ist. 10.0.52 ist überhaupt nicht Unicode-fähig, daher wird es die Zeichenfolgen nicht nach UTF-8 codieren, und es unterstützt nicht den Typ UnicodeString von Delphi 2009 + (oder sogar WideString, für diese Angelegenheit). Daher müssen alle Zeichenketten, die Sie in der TStrings speichern, bereits im UTF-8-Format vorliegen (und im Fall von Delphi 2009+ müssten sie immer noch in UTF-8 sein und 16-Bit-Zeichen für jede Codeeinheit anstelle von 8-Bit-Zeichen).

In der neuesten Indy-Version (10.6.2.5418 zum Zeitpunkt der Erstellung dieses Dokuments) ist TIdHTTP.Post(TStrings) vollständig Unicode-fähig und unterstützt UnicodeString.Es codiert beide name und value von name=value Paare, und verschlüsselt sie manuell (nicht mit TIdURI) in Übereinstimmung mit dem HTML5-Standard durch die Codierung eines Unicode-Zeichen nicht in der Set 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz*-._' zu UTF-8 (kann standardmäßig mit der AByteEncoding Parameter von Post()) vor Prozent-Codierung der resultierenden Bytes Oktette.

das gesagt ist, versuchen, etwas mehr wie folgt aus:

try 
    WXYZUserID :=  Trim(GetSettingsValue(mySQLQuery, wcsWXYZUserID, '')); 
    WXYZPassword :=  Trim(GetSettingsValue(mySQLQuery, wcsWXYZPassword, '')) 
    WXYZSecret :=  Trim(GetSettingsValue(mySQLQuery, wcsWXYZSecret, '')); 
    OAuthURL  :=  Trim(GetSettingsValue(mySQLQuery, wcsOAuthURL, '')); 

    WxyzHttp := TIdHttp.Create(nil); 
    try 
    WxyzHttp.ConnectTimeout := 60000; 

    IdLogFile := TIdLogFile.Create(WxyzHttp); 
    IdLogFile.Filename := 'Logs/WxyzHTTP' + FormatDateTime('yyyymmdd_hhnnsszzz',now) + '.log'; 
    IdLogFile.Active := True; 

    IdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(WxyzHttp); 
    IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvSSLv23; 
    IdSSLIOHandlerSocketOpenSSL1.Intercept := IdLogFile; 
    WxyzHttp.IOHandler := IdSSLIOHandlerSocketOpenSSL1; 

    if (WXYZSecret <> '') then 
     WxyzHttp.Request.CustomHeaders.Values['Authorization'] := 'Basic ' + WXYZSecret 
    else 
     WxyzHttp.Request.CustomHeaders.Values['Authorization'] := 'Basic ****************************************************************'; 

    WxyzHttp.Request.ContentType := 'application/x-www-form-urlencoded'; 
    WxyzHttp.Request.CharSet := 'utf-8'; 

    Serial := TStringList.Create; 
    try 
     Serial.Add('grant_type=password'); 

     if (WXYZUserID <> '') and (WXYZPassword <> '') then 
     begin 
     Serial.Add('username=' + WXYZUserID); 
     Serial.Add('password=' + WXYZPassword); 
     end else 
     begin 
     Serial.Add('username=****-*****'); 
     Serial.Add('password=***************'); 
     end; 

     Token := WxyzHttp.Post(OAuthURL, Serial); 
    finally 
     Serial.Free; 
    end; 
    finally 
    WxyzHttp.Free; 
    end; 
except 
    on E: Exception do 
    begin 
    DbgWebCatLog(wcmtDbg, 'GetSerialToken', E.ClassName + ' error raised, with message: ' + E.Message, ''); 
    Token := ''; 
    end; 
end; 
+0

Danke Remy. Durch die Umstrukturierung des Codes, der die tStringList erstellt, ist es gelungen. –

Verwandte Themen