Twitter API分片上传INIT请求认证失败(错误码32)求助
问题诊断与修复方案
核心原因:OAuth1签名基字符串参数未按字典序排序
Twitter的OAuth1认证要求所有参与签名的参数(包括请求体中的非OAuth参数)必须按参数名的ASCII升序排列,这是触发code:32认证错误的关键原因。你的代码构造签名基字符串时参数顺序不符合规范,导致签名验证失败。此外还有两处编码一致性问题需要修正。
具体问题点
- 签名参数顺序错误:当前
baseFormat_pic中的参数未按字典序排列,正确顺序需严格遵循参数名首字母的ASCII升序。 - 参数编码不一致:构造签名基字符串时,
total_bytes未做URL编码;media_type的编码逻辑需和请求体保持统一。 - 哈希编码格式错误:生成签名哈希时使用ASCII编码,可能引发潜在字符编码问题,应改用UTF-8。
修复后的代码片段
// 1. 按字典序排列所有参与签名的参数 var baseFormat_pic = "command={0}&media_type={1}&oauth_consumer_key={2}&oauth_nonce={3}&oauth_signature_method={4}&oauth_timestamp={5}&oauth_token={6}&oauth_version={7}&total_bytes={8}"; var encodedMediaType = HttpUtility.UrlEncode("video/mp4"); var encodedTotalBytes = HttpUtility.UrlEncode(fileBytes.ToString()); var baseString_pic = string.Format(baseFormat_pic, HttpUtility.UrlEncode("INIT"), encodedMediaType, HttpUtility.UrlEncode(oauth_consumer_key), HttpUtility.UrlEncode(oauth_nonce), HttpUtility.UrlEncode(oauth_signature_method), HttpUtility.UrlEncode(oauth_timestamp), HttpUtility.UrlEncode(oauth_token), HttpUtility.UrlEncode(oauth_version), encodedTotalBytes); // 2. 拼接并编码签名基字符串 baseString_pic = string.Concat("POST&", Uri.EscapeDataString(resource_url_pic), "&", Uri.EscapeDataString(baseString_pic)); var compositeKey_pic = string.Concat(Uri.EscapeDataString(oauth_consumer_secret), "&", Uri.EscapeDataString(oauth_token_secret)); string oauth_signature_pic; // 3. 使用UTF-8编码生成哈希 using (HMACSHA1 hasher = new HMACSHA1(Encoding.UTF8.GetBytes(compositeKey_pic))) { oauth_signature_pic = Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(baseString_pic))); } // 授权头构造逻辑保持不变(头内参数顺序不影响签名验证) var headerFormat_pic = "OAuth oauth_consumer_key=\"{3}\", oauth_token=\"{4}\", oauth_signature_method=\"{1}\", oauth_timestamp=\"{2}\", oauth_nonce=\"{0}\", oauth_version=\"{6}\", oauth_signature=\"{5}\""; var authHeader_pic = string.Format(headerFormat_pic, Uri.EscapeDataString(oauth_nonce), Uri.EscapeDataString(oauth_signature_method), Uri.EscapeDataString(oauth_timestamp), Uri.EscapeDataString(oauth_consumer_key), Uri.EscapeDataString(oauth_token), Uri.EscapeDataString(oauth_signature_pic), Uri.EscapeDataString(oauth_version) ); ServicePointManager.Expect100Continue = false; string reqUrl = resource_url_pic; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(reqUrl); request.Method = "POST"; // 请求体保持编码一致性 NameValueCollection nvc = new NameValueCollection(); nvc.Add("command", "INIT"); nvc.Add("total_bytes", fileBytes.ToString()); nvc.Add("media_type", "video/mp4"); var sb = new StringBuilder(); foreach (string key in nvc.Keys) { sb.AppendFormat("{0}={1}&", key, HttpUtility.UrlEncode(nvc[key].ToString())); } sb.Remove(sb.Length - 1, 1); var bytes = Encoding.UTF8.GetBytes(sb.ToString()); request.ContentLength = bytes.Length; request.Headers.Add("Authorization", authHeader_pic); request.ContentType = "application/x-www-form-urlencoded;charset=UTF-8"; using (var stream = request.GetRequestStream()) { stream.Write(bytes, 0, bytes.Length); } string result = ReadResult(request);
额外注意事项
- 确保
oauth_nonce每次请求生成唯一值,避免重复使用导致认证失败。 - 确认
resource_url_pic为https://upload.twitter.com/1.1/media/upload.json,且未附加任何查询参数(若有查询参数需一并纳入签名逻辑)。 total_bytes必须是视频文件的准确字节数,不能存在格式错误。
内容的提问来源于stack exchange,提问作者DorrisDormouse
相关产品推荐
相关产品推荐

