访问其他Twitter用户信息

时间:2014-12-30 22:17:30

标签: c# azure twitter custom-controls azure-mobile-services

我正在使用Azure移动服务来授权用户,现在我正尝试从提供商处获取其他用户信息。除了Twitter之外,我还为所有人工作。要对所有其他人进行身份验证,我正在使用类似的内容:

var identities = await user.GetIdentitiesAsync();
var result = new JObject();
var fb = identities.OfType<FacebookCredentials>().FirstOrDefault();
if (fb != null)
{
    var accessToken = fb.AccessToken;
    result.Add("facebook", await GetProviderInfo("https://graph.facebook.com/me?access_token=" + accessToken));
}

我可以做这样的事情:

var tw = identities.OfType<TwitterCredentials>().FirstOrDefault();
if (tw != null)
{
    var accessToken = tw.AccessToken;
    var accessTokenSecret = tw.AccessTokenSecret;

    result.Add("twitter", await
    GetProviderInfo("https://api.twitter.com/1.1/account/verify_credentials.json?token=" + accessToken + "&token_secret=" + accessTokenSecret + "&consumer_key=***************" + "&consumer_secret=******************************"));
}

还是我必须做一些完全不同的事情?

Woops,刚刚在这里找到了类似的问题:Twitter single url request

1 个答案:

答案 0 :(得分:1)

是的,这是可能的,但它比其他提供商的工作更多。

这是你的api控制器的代码(可能需要一些重构)

[HttpPost]
[Route("current/identity")]
public async Task<HttpResponseMessage> GetIdentityInfo()
{
    var currentUser = User as ServiceUser;

    if (currentUser != null)
    {
        var identities = await currentUser.GetIdentitiesAsync();

        var googleCredentials = identities.OfType<GoogleCredentials>().FirstOrDefault();

        if (googleCredentials != null)
        {
            var infos = await GetGoolgeDetails(googleCredentials);
            return Request.CreateResponse(HttpStatusCode.OK, infos);
        }

        var facebookCredentials = identities.OfType<FacebookCredentials>().FirstOrDefault();

        if (facebookCredentials!= null)
        {
            var infos = await GetFacebookDetails(facebookCredentials);
            return Request.CreateResponse(HttpStatusCode.OK, infos);
        }

        var microsoftCredentials = identities.OfType<MicrosoftAccountCredentials>().FirstOrDefault();

        if (microsoftCredentials != null)
        {
            var infos = await GetMicrosoftDetails(microsoftCredentials);
            return Request.CreateResponse(HttpStatusCode.OK, infos);
        }

        var twitterCredentials = identities.OfType<TwitterCredentials>().FirstOrDefault();

        if (twitterCredentials != null)
        {
            var infos = await GetTwitterDetails(currentUser, twitterCredentials);
            return Request.CreateResponse(HttpStatusCode.OK, infos);
        }
    }

    return Request.CreateResponse(HttpStatusCode.OK);
}

private async Task<JToken> GetTwitterDetails(ServiceUser currentUser, TwitterCredentials twitterCredentials)
{
    var twitterId = currentUser.Id.Split(':').Last();

    var accessToken = twitterCredentials.AccessToken;

    string consumerKey = ConfigurationManager.AppSettings["MS_TwitterConsumerKey"];
    string consumerSecret = ConfigurationManager.AppSettings["MS_TwitterConsumerSecret"];
    // Add this setting manually on your Azure Mobile Services Management interface.
    // You will find the secret on your twitter app configuration
    string accessTokenSecret = ConfigurationManager.AppSettings["FG_TwitterAccessTokenSecret"];

    var parameters = new Dictionary<string, string>();
    parameters.Add("user_id", twitterId);
    parameters.Add("oauth_token", accessToken);
    parameters.Add("oauth_consumer_key", consumerKey);

    OAuth1 oauth = new OAuth1();

    string headerString = oauth.GetAuthorizationHeaderString(
        "GET", "https://api.twitter.com/1.1/users/show.json",
        parameters, consumerSecret, accessTokenSecret);

    var infos = await GetProviderInfo("https://api.twitter.com/1.1/users/show.json?user_id=" + twitterId, headerString);
    return infos;
}

private async Task<JToken> GetMicrosoftDetails(MicrosoftAccountCredentials microsoftCredentials)
{
    var accessToken = microsoftCredentials.AccessToken;
    var infos = await GetProviderInfo("https://apis.live.net/v5.0/me/?method=GET&access_token=" + accessToken);
    return infos;
}

private async Task<JToken> GetFacebookDetails(FacebookCredentials facebookCredentials)
{
    var accessToken = facebookCredentials.AccessToken;
    var infos = await GetProviderInfo("https://graph.facebook.com/me?access_token=" + accessToken);
    return infos;
}

private async Task<JToken> GetGoolgeDetails(GoogleCredentials googleCredentials)
{
    var accessToken = googleCredentials.AccessToken;
    var infos = await GetProviderInfo("https://www.googleapis.com/oauth2/v3/userinfo?access_token=" + accessToken);
    return infos;
}

private async Task<JToken> GetProviderInfo(string url, string oauth1HeaderString = null)
{
    using (var client = new HttpClient())
    {

        if (oauth1HeaderString != null)
        {
            client.DefaultRequestHeaders.Authorization = System.Net.Http.Headers.AuthenticationHeaderValue.Parse(oauth1HeaderString); 
        }

        var resp = await client.GetAsync(url).ConfigureAwait(false);
        resp.EnsureSuccessStatusCode();
        string rawInfo = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
        return JToken.Parse(rawInfo);
    }
}

然后,您需要此类来构建有效的OAuth 1.0身份验证标头:

(几乎所有以下代码都来自LinqToTwitter,https://linqtotwitter.codeplex.com

public class OAuth1
{
    const string OAUTH_VERSION = "1.0";
    const string SIGNATURE_METHOD = "HMAC-SHA1";
    const long UNIX_EPOC_TICKS = 621355968000000000L;

    public string GetAuthorizationHeaderString(string method, string url, IDictionary<string, string> parameters, string consumerSecret, string accessTokenSecret)
    {
        string encodedAndSortedString = BuildEncodedSortedString(parameters);
        string signatureBaseString = BuildSignatureBaseString(method, url, encodedAndSortedString);
        string signingKey = BuildSigningKey(consumerSecret, accessTokenSecret);
        string signature = CalculateSignature(signingKey, signatureBaseString);
        string authorizationHeader = BuildAuthorizationHeaderString(encodedAndSortedString, signature);

        return authorizationHeader;
    }  

    internal void AddMissingOAuthParameters(IDictionary<string, string> parameters)
    {
        if (!parameters.ContainsKey("oauth_timestamp"))
            parameters.Add("oauth_timestamp", GetTimestamp());

        if (!parameters.ContainsKey("oauth_nonce"))
            parameters.Add("oauth_nonce", GenerateNonce());

        if (!parameters.ContainsKey("oauth_version"))
            parameters.Add("oauth_version", OAUTH_VERSION);

        if (!parameters.ContainsKey("oauth_signature_method"))
            parameters.Add("oauth_signature_method", SIGNATURE_METHOD);     
    }

    internal string BuildEncodedSortedString(IDictionary<string, string> parameters)
    {
        AddMissingOAuthParameters(parameters);

        return
            string.Join("&",
                (from parm in parameters
                 orderby parm.Key
                 select parm.Key + "=" + PercentEncode(parameters[parm.Key]))
                .ToArray());
    }

    internal virtual string BuildSignatureBaseString(string method, string url, string encodedStringParameters)
    {
        int paramsIndex = url.IndexOf('?');

        string urlWithoutParams = paramsIndex >= 0 ? url.Substring(0, paramsIndex) : url;

        return string.Join("&", new string[]
        {
            method.ToUpper(),
            PercentEncode(urlWithoutParams),
            PercentEncode(encodedStringParameters)
        });
    }

    internal virtual string BuildSigningKey(string consumerSecret, string accessTokenSecret)
    {
        return string.Format(
            CultureInfo.InvariantCulture, "{0}&{1}", 
            PercentEncode(consumerSecret),
            PercentEncode(accessTokenSecret));
    }

    internal virtual string CalculateSignature(string signingKey, string signatureBaseString)
    {
        byte[] key = Encoding.UTF8.GetBytes(signingKey);
        byte[] msg = Encoding.UTF8.GetBytes(signatureBaseString);

        KeyedHashAlgorithm hasher = new HMACSHA1();
        hasher.Key = key;
        byte[] hash = hasher.ComputeHash(msg);

        return Convert.ToBase64String(hash);
    }

    internal virtual string BuildAuthorizationHeaderString(string encodedAndSortedString, string signature)
    {
        string[] allParms = (encodedAndSortedString + "&oauth_signature=" + PercentEncode(signature)).Split('&');
        string allParmsString =
            string.Join(", ",
                (from parm in allParms
                 let keyVal = parm.Split('=')
                 where parm.StartsWith("oauth") || parm.StartsWith("x_auth")
                 orderby keyVal[0]
                 select keyVal[0] + "=\"" + keyVal[1] + "\"")
                .ToList());
        return "OAuth " + allParmsString;
    }

    internal virtual string GetTimestamp()
    {
        long ticksSinceUnixEpoc = DateTime.UtcNow.Ticks - UNIX_EPOC_TICKS;
        double secondsSinceUnixEpoc = new TimeSpan(ticksSinceUnixEpoc).TotalSeconds;
        return Math.Floor(secondsSinceUnixEpoc).ToString(CultureInfo.InvariantCulture);
    }

    internal virtual string GenerateNonce()
    {
        return new Random().Next(111111, 9999999).ToString(CultureInfo.InvariantCulture);
    }

    internal virtual string PercentEncode(string value)
    {
        const string ReservedChars = @"`!@#$^&*()+=,:;'?/|\[] ";

        var result = new StringBuilder();

        if (string.IsNullOrWhiteSpace(value))
            return string.Empty;

        var escapedValue = Uri.EscapeDataString(value);

        // Windows Phone doesn't escape all the ReservedChars properly, so we have to do it manually.
        foreach (char symbol in escapedValue)
        {
            if (ReservedChars.IndexOf(symbol) != -1)
            {
                result.Append('%' + String.Format("{0:X2}", (int)symbol).ToUpper());
            }
            else
            {
                result.Append(symbol);
            }
        }

        return result.ToString();
    }
}