Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi Twitter-无法通过OAuth(401)错误进行身份验证_Delphi_Twitter_Oauth - Fatal编程技术网

Delphi Twitter-无法通过OAuth(401)错误进行身份验证

Delphi Twitter-无法通过OAuth(401)错误进行身份验证,delphi,twitter,oauth,Delphi,Twitter,Oauth,所以,我正在用Delphi做一个简单的twitter应用程序,因为我找不到一个已经可以使用的库,所以我决定创建自己的库。通过身份验证过程,我会遵循所有步骤,并获得访问令牌和秘密令牌 当我尝试使用它们时(在下面的代码中),我得到了错误{“error”:“无法通过OAuth进行身份验证。”} 读和写请求(验证和发布)都是如此。任何帮助都将不胜感激,因为我一直为此把头撞在墙上 下面代码中的命令是注释正上方变量的内容 EDIT:即使只知道可能导致“无法使用OAuth进行身份验证”而不是更具体的错误(“无

所以,我正在用Delphi做一个简单的twitter应用程序,因为我找不到一个已经可以使用的库,所以我决定创建自己的库。通过身份验证过程,我会遵循所有步骤,并获得访问令牌和秘密令牌

当我尝试使用它们时(在下面的代码中),我得到了错误{“error”:“无法通过OAuth进行身份验证。”}

读和写请求(验证和发布)都是如此。任何帮助都将不胜感激,因为我一直为此把头撞在墙上

下面代码中的命令是注释正上方变量的内容

EDIT:即使只知道可能导致“无法使用OAuth进行身份验证”而不是更具体的错误(“无效签名”、“缺少参数”)的原因,也会大有帮助

编辑2:Wireshark数据包结果。

HTTP/1.1 401 Unauthorized
Date: Tue, 06 Sep 2011 20:11:13 GMT
Server: hi
Status: 401 Unauthorized
WWW-Authenticate: OAuth realm="http://api.twitter.com"
X-Runtime: 0.01306
Content-Type: application/json; charset=utf-8
Content-Length: 114
Cache-Control: no-cache, max-age=300
Set-Cookie: _twitter_sess=xxxxxxxxxxx; domain=.twitter.com; path=/; HttpOnly
Expires: Tue, 06 Sep 2011 20:16:13 GMT
Vary: Accept-Encoding
Connection: close
{"error":"Could not authenticate with OAuth.","request":"\/1\/statuses\/update.json?status=This%20is%20a%20test."}
代码:


所以我发现在这条线上:

fHTTP.Request.CustomHeaders.AddValue('Authorization',AuthHeader)

组件处理自定义标题的方式是,文本的分隔符是逗号。这意味着程序在我为OAuth包含的每个参数之后添加了\r\n(新行)。难怪失败了!Twitter甚至没有收到参数

因为我在将标题添加到标题之前检查了标题,所以我甚至认为这不是问题所在


谢谢你的帮助!否则我可能不会深入研究代码。

我制作了一个简单的库/类来发送状态更新(发布消息):


首先,检查机器上的日期/时间设置。那么,如何生成签名呢?我在你的代码中看不到这一点。你确定这是对的吗?第三,您是否尝试过解析响应的标题(或使用Wireshark嗅探它们)?其中可能有错误的详细信息。日期和时间设置正确,与签名相同(尽管此特定签名中需要包含哪些内容)。如果其中任何一个都不正确,那么使用相同内容的身份验证步骤也会失败。此外,这些问题还存在特定的错误。我已经查看了原始标题,其中包含的唯一错误是我列出的错误。这就是为什么我如此困惑的原因。它返回了细节。我已尝试使用无效令牌进行授权。以下是我得到的响应(在Java中有getErrorStream,它返回任何有用的数据,即使服务器使用非200进行回复):{“error”:“Invalid\/expired Token”,“request”:“\/1\/account\/verify\/u credentials.json”}。试着获取数据。我认为最简单的方法是使用Wireshark。就是这样,json响应错误是“无法通过OAuth进行身份验证”。“我刚刚运行了Wireshark,没有其他与之相关的错误。用wireshark结果编辑的原始帖子。我当时不知道。尝试使用其他工具或库运行相同的请求,嗅探HTTP包并将其与您的进行比较。例如,Twitter上有twurl()或许多用于Java、C#、Ruby、Python等的库。
function TTwitter.SendRequest(Method: String; URI: String; Params: Array of String): ISuperObject;
const
  AuthHeaderFormat = 'OAuth oauth_nonce="%s", oauth_signature_method="%s", oauth_timestamp="%s", oauth_consumer_key="%s", oauth_token="%s", oauth_signature="%s", oauth_version="%s"';
var
  oauth_nonce,
  oauth_timestamp,
  SignKey,
  BaseString,
  Signature,
  AuthHeader,
  ResponseStr : String;
  BaseStringParams : Array of String;
  JSON : ISuperObject;
  I, J : Integer;
  EmptyParams : TStringList;
begin
  oauth_nonce := GenerateNonce;
  oauth_timestamp := GenerateTimeStamp;
  SignKey := fConsumerSecret + '&' + fAccessToken;
  J := 0;
  SetLength(BaseStringParams, Length(Params) + 6);
  For I := Low(Params) To High(Params) Do
    begin
    BaseStringParams[J] := Params[I];
    Inc(J);
  end;
  BaseStringParams[J] := 'oauth_consumer_key=' + fConsumerKey;
  BaseStringParams[J + 1] := 'oauth_nonce=' + oauth_nonce;
  BaseStringParams[J + 2] := 'oauth_signature_method=' + oauth_signature_method;
  BaseStringParams[J + 3] := 'oauth_token=' + fOAuthToken;
  BaseStringParams[J + 4] := 'oauth_timestamp=' + oauth_timestamp;
  BaseStringParams[J + 5] :=  'oauth_version=' + oauth_version;
  BaseString := CreateBaseString('POST', URI, BaseStringParams);
  //POST&http%3A%2F%2Fapi.twitter.com%2F1%2Fstatuses%2Fupdate.json&oauth_consumer_key%3DXXXXXXXXXXXXXXXX%26oauth_nonce%3D0F95A680F2231F689C702FCECAD1D449%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1314988258%26oauth_token%3DXXXXXX-XXXXXXXXXXXXXXXX%26oauth_version%3D1.0%26status%3DThis%2520is%2520a%2520test.
  AuthHeader := Format(AuthHeaderFormat, [oauth_nonce,
                                          oauth_signature_method,
                                          oauth_timestamp,
                                          fConsumerkey,
                                          fOAuthToken,
                                          Signature,
                                          oauth_version]);
  //OAuth oauth_nonce="0F95A680F2231F689C702FCECAD1D449", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1314988258", oauth_consumer_key="XXXXXXXXXXXXXXXXXX", oauth_token="XXXXXX-XXXXXXXXXXXXXXXX", oauth_signature="XXXXXXXXXXXXXXXXXXXXX", oauth_version="1.0"
  fHTTP.Request.CustomHeaders.AddValue('Authorization', AuthHeader);
  EmptyParams := TStringList.Create;
  Try
    If Length(Params) > 0 Then
      begin
      URI := URI + '?';
      For I := Low(Params) To High(Params) Do
        begin
        URI := URI + Params[I] + '&';
      end;
      URI := Copy(URI, 1, Length(URI) - 1);
      //http://api.twitter.com/1/statuses/update.json?status=This%20is%20a%20test.
    end;
    If Method = 'POST' Then
      begin
      ResponseStr := fHTTP.Post(URI, EmptyParams);
    end
    Else If Method = 'GET' Then
      begin
      ResponseStr := fHTTP.Get(URI);
    end;
    JSON := SO(ResponseStr);
    Result := JSON;
  Except
    On E:EIdHTTPProtocolException Do
      begin
      MessageBox(0, PChar(E.ErrorMessage), '', 0);
      //{"error":"Could not authenticate with OAuth.","request":"\/1\/statuses\/update.json?status=This%20is%20a%20test."}
    end;
  end;
  EmptyParams.Free;
end;