401 error while trying to call Twitter stream API

2019-05-07 19:28发布

I'm at my wit's end with this, I have looked all over here and while questions similar to mine have been asked, I can't find this exact one with any answers yet.

I have been trying to call https://stream.twitter.com/1.1/statuses/filter.json from within a C# console app for days now and keep getting at 401 Unauthorized error that no matter what I do won't go away. Works fine for anything not streaming as well.

const string streamUrl = "https://stream.twitter.com/1.1/statuses/filter.json";
const string oauth_token = "XXX-XXXXX";
const string oauth_token_secret = "XXXXXXXXXXXX";
const string oauth_consumer_key = "XXXXXXXXXXXXX";
const string oauth_consumer_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

// oauth implementation details
const string oauth_version = "1.0a";
const string oauth_signature_method = "HMAC-SHA1";

// unique request details
var oauth_nonce = Convert.ToBase64String(
    new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
var timeSpan = DateTime.UtcNow
    - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();

// create oauth signature
const string baseFormat = "oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" +
    "&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}&track=twitter";

var baseString = string.Format(baseFormat,
    oauth_consumer_key,
    oauth_nonce,
    oauth_signature_method,
    oauth_timestamp,
    oauth_token,
    oauth_version);

string oauth_signature;

var compositeKey = string.Concat(Uri.EscapeDataString(oauth_consumer_secret),
    "&", Uri.EscapeDataString(oauth_token_secret));

using (var hasher = new HMACSHA1(Encoding.ASCII.GetBytes(compositeKey)))
{
    oauth_signature = Convert.ToBase64String(hasher.ComputeHash(Encoding.ASCII.GetBytes(baseString)));
}

// create the request header
const string headerFormat = "OAuth oauth_consumer_key=\"{0}\", oauth_nonce=\"{1}\", " +
    "oauth_signature=\"{2}\", oauth_signature_method=\"{3}\", " +
    "oauth_timestamp=\"{4}\", oauth_token=\"{5}\", " +
    "oauth_version=\"{6}\"";

var authHeader = string.Format(headerFormat,
    Uri.EscapeDataString(oauth_consumer_key),
    Uri.EscapeDataString(oauth_nonce),
    Uri.EscapeDataString(oauth_signature),
    Uri.EscapeDataString(oauth_signature_method),
    Uri.EscapeDataString(oauth_timestamp),
    Uri.EscapeDataString(oauth_token),
    Uri.EscapeDataString(oauth_version));

const string postparameters = "track=twitter";

streamUrl = string.Format("{0}?{1}", streamUrl, postparameters);

while (true)
{
    var timeLineRequest = (HttpWebRequest)WebRequest.Create(streamUrl);
    timeLineRequest.Headers.Add("Authorization", authHeader);
    var encode = System.Text.Encoding.GetEncoding("utf-8");

    ServicePointManager.Expect100Continue = false;

    if (postparameters.Length > 0)
    {
        timeLineRequest.Method = "POST";
        timeLineRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";

        byte[] _twitterTrack = encode.GetBytes(postparameters);

        timeLineRequest.ContentLength = _twitterTrack.Length;
        Stream _twitterPost = timeLineRequest.GetRequestStream();
        _twitterPost.Write(_twitterTrack, 0, _twitterTrack.Length);
        _twitterPost.Close();
    }

    var webResponse = (HttpWebResponse)timeLineRequest.GetResponse();
    var responseStream = new StreamReader(webResponse.GetResponseStream(), encode);

    while (true)
    {
        var jsonText = responseStream.ReadLine();

        //Success
        int wait = 250;

        //Write Status
        var status = string.Empty;
        var json = new DataContractJsonSerializer(status.GetType());
        byte[] byteArray = Encoding.UTF8.GetBytes(jsonText);
        var stream = new MemoryStream(byteArray);
        status = json.ReadObject(stream) as string;
        Console.Beep();
        Console.WriteLine(status);
    }               
}

I would really appreciate to see if anyone else has passed this hurdle. I'm tired of cursing at this.

1条回答
贼婆χ
2楼-- · 2019-05-07 19:49

You haven't included the HTTP method or the base URL into your baseString before you compute the signature. This is taken from the Twitter site:

Creating the signature base string

The three values collected so far must be joined to make a single string, from which the signature will be generated. This is called the signature base string by the OAuth specification.

To encode the HTTP method, base URL, and parameter string into a single string:

  1. Convert the HTTP Method to uppercase and set the output string equal to this value.

  2. Append the '&' character to the output string.

  3. Percent encode the URL and append it to the output string.

  4. Append the '&' character to the output string.

  5. Percent encode the parameter string and append it to the output string.

查看更多
登录 后发表回答