gpt4 book ai didi

delphi - 当密码为俄语时,通过 HTTPS 授权失败 TIdHTTP

转载 作者:行者123 更新时间:2023-12-01 22:16:15 24 4
gpt4 key购买 nike

我尝试通过以下代码使用 TIdHTTP(Indy 10.6.0 和 Delphi XE5)测试我的 Web 服务:

GIdDefaultTextEncoding := encUTF8;
HTTP.IOHandler.DefStringEncoding := IndyTextEncoding_UTF8;
Http.Request.UserName := AUser;
Http.Request.Password := APass;
Http.Request.Accept := 'text/javascript';
Http.Request.ContentType := 'application/json';
Http.Request.ContentEncoding := 'utf-8';
Http.Request.URL := 'https://sameService';
Http.MaxAuthRetries := 1;
Http.Request.BasicAuthentication := True;
TIdSSLIOHandlerSocketOpenSSL(HTTP.IOHandler).SSLOptions.Method := sslvSSLv3;
HTTP.HandleRedirects := True;

UTF-8 格式的“AUser”和“APass”。当“APass”具有相同的俄语字符时,我无法登录。通过“HTTP 分析”我看到:

...
Authorization: Basic cDh1c2VyOj8/Pz8/PzEyMw==

从 Base 64 解码(base64decode.org)我们可以看到:

p8user:??????123

为什么 DefStringEncoding 不起作用?

最佳答案

TIdHTTP 的身份验证系统没有 TIdIOHandler 或其 DefStringEncoding 属性的概念。

在内部,TIdBasicAuthentication 使用 TIdEncoderMIME.Encode(),但不指定任何编码。 TIdEncoder.Encode() 默认为 8bit 编码,因此不受 GIdDefaultTextEncoding 影响。

如果您需要通过 BASIC 身份验证发送 UTF-8 编码的密码,则必须手动对 UTF-8 数据进行编码,并将生成的八位字节存储到 字符串,然后8位编码器可以按原样处理八位字节,例如:

Http.Request.Password := BytesToStringRaw(IndyTextEncoding_UTF8.GetBytes(APass));

另一方面,例如,Indy 的 DIGEST 身份验证使用 TIdHashMessageDigest5.HashStringAsHex(),而 TIdHash.HashString() 则使用不默认为任何特定编码,它取决于 GIdDefaultTextEncoding

因此,您必须根据您使用的身份验证谨慎对待密码编码方式。为了解决这种差异,您可以尝试不对 TIdHTTP.Request.Password 本身进行编码,而是在 TIdHTTP.OnAuthorization 事件中对密码进行编码,而不是在 正在使用 BASIC 身份验证,例如:

Http.Request.Password := APass;

...

procedure TMyForm.HttpAuthorization(Sender: TObject;
Authentication: TIdAuthentication; var Handled: Boolean);
begin
if Authentication is TIdBasicAuthentication then
begin
Authentication.Password := BytesToStringRaw(IndyTextEncoding_UTF8.GetBytes(TheDesiredPasswordHere));
Handled := True;
end;
end;
<小时/>

更新:

Internally, TIdBasicAuthentication uses TIdEncoderMIME.Encode(), but without specifying any encoding.

最后一部分不再正确。 TIdBasicAuthentication 于 2016 年进行了更新,现在将编码传递给 TIdEncoderMIME.Encode()。当 HTTP 服务器请求 BASIC 身份验证时,TIDBasicAuthentication 现在会检查服务器的 WWW-Authenticate header 是否包含以下属性之一: charsetaccept-charsetencodingenc(按该顺序)。如果找到,则将指定的字符集传递给 Encode(),否则使用 ISO-8859-1(有一个 TODO如果用户名或密码包含 ISO-8859-1 中不存在的任何字符,则使用 UTF-8 的代码。

如果您想确保在 BASIC 身份验证中使用 UTF-8,最好将 Request.BasicAuthentication 设置为 False 并使用 Request.CustomHeaders 提供您自己的 Authorization header ,例如:

Http.Request.BasicAuthentication := False;
Http.Request.CustomHeaders.Values['Authorization'] := 'Basic ' + TIdEncoderMIME.EncodeString(AUser + ':' + APass, IndyTextEncoding_UTF8);

或者,您可能可以通过更新TIdHTTP.OnAuthorization事件中 protected TIdBasicAuthentication.FCharset成员来逃脱(在解析服务器的 WWW-Authenticate header 后触发),例如:

Http.Request.Password := APass;

...

type
TIdBasicAuthenticationAccess = class(TIdBasicAuthentication)
end;

procedure TMyForm.HttpAuthorization(Sender: TObject;
Authentication: TIdAuthentication; var Handled: Boolean);
begin
if Authentication is TIdBasicAuthentication then
begin
TIdBasicAuthenticationAccess(Authentication).FCharset := 'utf-8';
Authentication.Password := TheDesiredPasswordHere;
Handled := True;
end;
end;

关于delphi - 当密码为俄语时,通过 HTTPS 授权失败 TIdHTTP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29205107/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com