5

我正在使用带有 Indy 10 的 Delphi XE2 来访问 Ubuntu One API。到现在为止还挺好。如所述,我能够从云端获取 OAuth 令牌。现在我想开始使用 API(如前所述):

function TUbuntuOneApi.DoRequest(const URL: String): String;
var
  RequestParams: TStringList;
  HeaderIndex: Integer;
const
  OAuthAuthorisationHeader = 'OAuth realm="", oauth_version="%s", oauth_nonce="%s", oauth_timestamp="%s", oauth_consumer_key="%s", oauth_token="%s", oauth_signature_method="%s", oauth_signature="%s"';

begin
  RequestParams := SignOAuthRequestParams(URL, fOAuthAppToken, fOAuthAccessToken);

{  OAuth realm="", oauth_version="1.0",
  oauth_nonce="$nonce", oauth_timestamp="$timestamp",
  oauth_consumer_key="$consumer_key", oauth_token="$token",
  oauth_signature_method="PLAINTEXT",
  oauth_signature="$consumer_secret%26$token_secret"
  }

  HeaderIndex := IdHTTP.Request.CustomHeaders.IndexOfName('Authorization');
  if HeaderIndex >= 0 then
  begin
    IdHTTP.Request.CustomHeaders.Delete(HeaderIndex);
  end;

  // Solving: http://stackoverflow.com/questions/7323036/twitter-could-not-authenticate-with-oauth-401-error
  IdHTTP.Request.CustomHeaders.FoldLines := false;

  IdHTTP.Request.CustomHeaders.AddValue('Authorization', Format(OAuthAuthorisationHeader, [
      TIdURI.URLDecode(RequestParams.Values['oauth_version']),
      TIdURI.URLDecode(RequestParams.Values['oauth_nonce']),
      TIdURI.URLDecode(RequestParams.Values['oauth_timestamp']),
      TIdURI.URLDecode(RequestParams.Values['oauth_consumer_key']),
      TIdURI.URLDecode(RequestParams.Values['oauth_token']),
      TIdURI.URLDecode(RequestParams.Values['oauth_signature_method']),
      TIdURI.URLDecode(RequestParams.Values['oauth_signature'])
    ]));

  // Execute
  Result := IdHTTP.Get(URL);
  RequestParams.Free;
end;

function TUbuntuOneApi.Test: String;
begin
  //Result := DoRequest('https://one.ubuntu.com/api/file_storage/v1');
  Result := DoRequest('https://one.ubuntu.com/api/account/');
end;

调用https://one.ubuntu.com/api/file_storage/v1会导致“401 UNAUTHORIZED”。调用https://one.ubuntu.com/api/account/会导致“400 BAD REQUEST”。OAuth 库来自SourceForge并与 Dropbox 一起使用(如果 OAuth-Params 在查询字符串中,Dropbox 接受它们)。令牌是正确且有效的。我究竟做错了什么?

顺便提一句:

function SignOAuthRequestParams(const URL: String; OAuthAppToken, OAuthAccessToken: TOAuthToken): TStringList;
var
  Consumer: TOAuthConsumer;
  ARequest: TOAuthRequest;
  Response: String;
  HMAC: TOAuthSignatureMethod;
begin
  HMAC := TOAuthSignatureMethod_PLAINTEXT.Create;
  // Consumer erzeugen
  Consumer := TOAuthConsumer.Create(OAuthAppToken.Key, OAuthAppToken.Secret);

  // Request erzeugen
  ARequest := TOAuthRequest.Create(URL);
  ARequest := ARequest.FromConsumerAndToken(Consumer, OAuthAccessToken, URL);
  ARequest.Sign_Request(HMAC, Consumer, OAuthAccessToken);

  Result := TStringList.Create;
  Result.AddStrings(ARequest.Parameters);

  ARequest.Free;
  Consumer.Free;
  HMAC.Free;
end;
4

1 回答 1

1

此时,新创建的令牌可用于在 Ubuntu SSO 服务上向其他方法进行身份验证,但尚不能与 Ubuntu One API 一起使用。我们需要告诉 Ubuntu One 从 SSO 服务中复制新创建的令牌。这是通过向GET 以下 URL 发出请求来完成的,并使用新的 OAuth 令牌进行签名。来自Ubuntu One:授权页面

惭愧,我忘了这样做。

于 2012-11-10T14:19:38.207 回答