2014-12-30 99 views
1

我正在使用Azure移動服務來授權用戶,現在正在嘗試從提供程序獲取其他用戶信息。除了Twitter以外,我都爲它們工作。爲驗證所有我用類似這樣的東西其他:訪問其他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

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

這是您的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認證頭:

(幾乎所有的以下代碼is from 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 = @"`[email protected]#$^&*()+=,:;'?/|\[] "; 

     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(); 
    } 
} 
+0

這是英勇的!它仍然有效嗎?現在有更簡單的方法嗎?難怪它沒有出現在樣本中。 – tofutim