Получение InstaApp OAuth-токена доступа от Delphi
У меня проблемы с получением токена доступа от API Instapaper с помощью пакета Overbyte ICS. Странно то, что я могу получить токен доступа с помощью Indy. Я использую Delphi XE2 и ICS версии 7.
В целях отладки я использую фиксированные строки для данных поста и заголовков авторизации. Поскольку код Indy работает, проблема, похоже, не связана с сигнатурой.
Я хотел бы, чтобы это работало с ICS ... есть идеи, почему код не работает? Я получаю недопустимую ошибку подписи (подпись не соответствует ожидаемому значению). Заголовок авторизации и тело сообщения должны совпадать с тем, что я отправляю с помощью Indy, поэтому похоже, что это как-то связано с запросом ICS.
Вот код Indy, который работает (я получаю oauth_token и oauth_token_secret обратно)
var
Params: TStringList;
AuthHeader: STring;
idHTTP: TIDHTTP;
SSLIOHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
idHTTP := TIDHTTP.Create(Self);
SslIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(Self);
idHTTP.IOHandler := SSLIOHandler;
idHTTP.HTTPOptions := [];
Params := TStringList.Create;
Params.Add('x_auth_mode=client_auth');
Params.Add('x_auth_password=mypassword');
Params.Add('x_auth_username=myusername%40gmail.com');
idHTTP.Request.Host := 'https://www.instapaper.com';
AuthHeader := 'Authorization: ' + 'OAuth oauth_consumer_key="myconsumerkey", oauth_nonce="BAFWMTGFXNXSTNKUENBC", oauth_signature_method="HMAC-SHA1", oauth_signature="sEfq8gHlHYfrmLy5u0kKBgTYmVA%3D", oauth_timestamp="1369669197", oauth_version="1.0"';
idHTTP.request.CustomHeaders.Add(AuthHeader);
Response := idHTTP.Post('https://www.instapaper.com/api/1/oauth/access_token', Params);
end;
Вот код ICS, который терпит неудачу (неверная подпись):
var
PostData: AnsiString;
begin
PostData := 'x_auth_mode=client_auth&x_auth_password=mypassword&x_auth_username=myusername%40gmail.com';
SSLHTTPClient := TSslHttpCli.Create(nil);
With SSLHTTPClient do
begin
RcvdStream := TMemoryStream.Create;
SendStream := TMemoryStream.Create;
SendStream.Seek(0, soFromBeginning);
SendStream.Write(PostData[1], Length(PostData));
SendStream.Seek(0, soFromBeginning);
URL := 'https://www.instapaper.com/api/1/oauth/access_token';
OnRequestDone := SSLHTTPClientRequestDone;
OnBeforeHeaderSend := HTTPClientBeforeHeaderSend; // add the authorization header
SslContext := TSslContext.Create(SSLHTTPClient);
PostAsync;
end;
end;
procedure TInstapaperOAuth.HTTPClientBeforeHeaderSend(Sender: TObject; const Method: string; Headers: TStrings);
var
Header: String;
begin
Header := 'Authorization: ' + 'OAuth oauth_consumer_key="myconsumerkey", oauth_nonce="BAFWMTGFXNXSTNKUENBC", oauth_signature_method="HMAC-SHA1", oauth_signature="sEfq8gHlHYfrmLy5u0kKBgTYmVA%3D", oauth_timestamp="1369669197", oauth_version="1.0"';
Headers.Add(Header);
end;
1 ответ
Я принимаю вышеуказанный комментарий как ответ на этот вопрос. Поэтому, чтобы обойти эту проблему, обновите HTTPClientBeforeHeaderSend, чтобы заменить запись хоста, добавив заголовок oauth:
procedure TInstapaperOAuth.HTTPClientBeforeHeaderSend(Sender: TObject; const Method: string; Headers: TStrings);
var
Header: String;
I: Integer;
begin
Header := 'Authorization: ' + 'OAuth oauth_consumer_key="myconsumerkey", oauth_nonce="BAFWMTGFXNXSTNKUENBC", oauth_signature_method="HMAC-SHA1", oauth_signature="sEfq8gHlHYfrmLy5u0kKBgTYmVA%3D", oauth_timestamp="1369669197", oauth_version="1.0"';
Headers.Add(Header);
//=======================================
// find the host record and replace it
//=======================================
for I := 0 to Headers.Count - 1 do
begin
if pos('Host:',Headers.Strings[I]) > 0 then
begin
Headers.Strings[I] := 'Host: www.instapaper.com';
break;
end;
end;
end;