如何将DotNetOpenAuth与Netflix API一起使用?

时间:2012-09-03 22:29:08

标签: c# .net dotnetopenauth netflix

这是我到目前为止所做的,但它不起作用,因为我不明白DotNetOpenAuth应该如何工作。我只需要用钥匙签下结果,但我没有运气。一切似乎都指向我需要让客户端授权我的访问权限,但我只需要签名,因为我不需要用户来处理此请求。

请参阅http://developer.netflix.com/docs/read/Security标有“Netflix API请求”

的部分
public class class1
{
    private void Main()
    {
        string consumerKey = "<MyAPIKey>";
        string consumerSecret = "<MyAPISharedSecret>";
        var tokenManager = new InMemoryTokenManager(consumerKey, consumerSecret);

        MessageReceivingEndpoint oauthEndpoint =
            new MessageReceivingEndpoint(new Uri("http://api-public.netflix.com/catalog/titles/index"),
                                         HttpDeliveryMethods.PostRequest);
        WebConsumer consumer = new WebConsumer(
            new ServiceProviderDescription
                {
                    RequestTokenEndpoint = oauthEndpoint,
                    UserAuthorizationEndpoint = oauthEndpoint,
                    AccessTokenEndpoint = oauthEndpoint,
                    TamperProtectionElements =
                        new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement()},
                },
            tokenManager);


        var result = consumer.Channel.Request(new AccessProtectedResourceRequest());


    }

    internal class InMemoryTokenManager : IConsumerTokenManager
    {
        private Dictionary<string, string> tokensAndSecrets = new Dictionary<string, string>();

        public InMemoryTokenManager(string consumerKey, string consumerSecret)
        {
            if (string.IsNullOrEmpty(consumerKey))
            {
                throw new ArgumentNullException("consumerKey");
            }

            this.ConsumerKey = consumerKey;
            this.ConsumerSecret = consumerSecret;
        }

        public string ConsumerKey { get; private set; }

        public string ConsumerSecret { get; private set; }

        public string GetTokenSecret(string token)
        {
            return this.tokensAndSecrets[token];
        }

        public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response)
        {
            this.tokensAndSecrets[response.Token] = response.TokenSecret;
        }

        public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken,
                                                             string accessTokenSecret)
        {
            this.tokensAndSecrets.Remove(requestToken);
            this.tokensAndSecrets[accessToken] = accessTokenSecret;
        }

        public TokenType GetTokenType(string token)
        {
            throw new NotImplementedException();
        }
    }
}

1 个答案:

答案 0 :(得分:3)

您的实际问题应该是“是否可以使用DotNetOpenAuth签署带或不带访问令牌的请求?”,回答我应该说我不知道​​的问题,甚至我也找不到它阅读DotNetOpenAuth代码库。

没有单页的文档可用于DotNetOpenAuth,而且代码库非常庞大,以至于您无法阅读它并了解它所支持的内容。

我认为制作未经身份验证的请求不是问题,因为它只是添加到您的请求中的查询字符串参数。

但要签署请求,您需要遵循一个简单的过程:

  1. 收集请求参数
  2. 计算签名
  3. 提出请求(签名/保护)
  4. 收集请求参数

    这些基本上是两类参数,oauth特定参数和Netflix API特定参数。

    OAuth特定参数中有nonce,这是您可以用来生成随机数值的代码:

    public static string GenerateNonce()
    {
        byte[] bytes = new byte[32];
        var first = Guid.NewGuid().ToByteArray();
        var second = Guid.NewGuid().ToByteArray();
        for (var i = 0; i < 16; i++)
            bytes[i] = first[i];
        for (var i = 16; i < 32; i++)
            bytes[i] = second[i - 16];
        var result = Convert.ToBase64String(bytes, Base64FormattingOptions.None);
        result = new string(result.ToCharArray().Where(char.IsLetter).ToArray());
        return result;
    }
    

    另一个特定于OAuth的参数是timestamp,这是您可以用来计算时间戳的代码:

    DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds
    

    其他oauth特定参数易于配置,无需为其编写特定代码。

    API特定参数是您添加到查询字符串或授权标头(oauth_signature本身除外)或正文请求(如果请求内容类型为application / x-www-form-urlencoded)的任何值。

    计算签名

    要创建签名请求或受保护签名,您需要计算签名,除了创建签名密钥的方式外,该签名几乎相同:

    1. 计算签名基本字符串
    2. 计算签名密钥
    3. 通过使用签名密钥签名签名基本字符串来创建签名
    4. 要计算签名基本字符串,您需要先将所有参数连接成一个字符串,百分比编码整个字符串。这是帮助您进行百分比编码的代码:

      public static string Encode(string source)
      {
          Func<char, string> encodeCharacter = c => {
              if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '.' || c == '-' || c == '_' || c == '~'))
                  return new string(c, 1);
              return EncodeCharacter(c);
          };
          return string.Concat(source.ToCharArray().Select(encodeCharacter));
      }
      

      您还需要按字母顺序对参数进行排序,并使用“&amp;”进行连接。以下是您可能必须编写的代码:

      public static string CalculateParameterString(KeyValuePair<string, string>[] parameters)
      {
          var q = from entry in parameters
                  let encodedkey = PercentEncode.Encode(entry.Key)
                  let encodedValue = PercentEncode.Encode(entry.Value)
                  let encodedEntry = encodedkey + "=" + encodedValue
                  orderby encodedEntry
                  select encodedEntry;
          var result = string.Join("&", q.ToArray());
          return result;
      }
      

      让我们调用上面的字符串'参数字符串'。然后,要计算签名基本字符串,您只需要使用'&amp;'将请求的http动词,请求的url和参数字符串连接在一起。您还需要先对百分比进行编码。这是代码:

      public static string CalcualteSignatureBaseString(string httpMethod, string baseUri, string parametersString)
      {
          return httpMethod.ToUpper() + "&" + PercentEncode.Encode(baseUri) + "&" + PercentEncode.Encode(parametersString);
      }
      

      创建签名基本字符串后,下一步就是计算签名密钥。

      • 如果您只需要签署请求,则只能根据您的使用者密钥(共享密钥)创建签名密钥。这是用于签署请求的签名密钥。
      • 在授权过程中,如果您刚刚发出了请求令牌请求并收到了临时oauth令牌,那么您的演唱密钥将基于您的使用者密钥和该oauth令牌。这是用于请求获取访问令牌的签名密钥。
      • 如果用户授权您的应用程序并且您拥有相关的访问令牌,那么您的签名密钥将是您的使用者密钥和访问令牌。这是发出受保护请求的签名密钥。

      这是将生成签名密钥的代码:

      public static string GetSigningKey(string ConsumerSecret, string OAuthTokenSecret = null)
      {
          return ConsumerSecret + "&" + (OAuthTokenSecret != null ? OAuthTokenSecret : "");
      }
      

      在您的情况下,要创建已签名的请求,您只需要为OAuthTokenSecret参数传递null值。

      好的,现在你有了一个签名基本字符串,你现在需要做的就是使用HMAC-SHA1算法进行签名:

      public static string Sign(string signatureBaseString, string signingKey)
      {
          var keyBytes = System.Text.Encoding.ASCII.GetBytes(signingKey);
          using (var myhmacsha1 = new System.Security.Cryptography.HMACSHA1(keyBytes)) {
              byte[] byteArray = System.Text.Encoding.ASCII.GetBytes(signatureBaseString);
              var stream = new MemoryStream(byteArray);
              var signedValue = myhmacsha1.ComputeHash(stream);
              var result = Convert.ToBase64String(signedValue, Base64FormattingOptions.None);
              return result;
          }
      }
      

      总结一下,这是计算签名的整个过程:

          public virtual string GetSignature(string consumerSecret, string tokenSecret, string uri, string method, params ParameterSet[] parameters)
          {
              var allParameters = parameters.SelectMany(p => p.ToList()).ToArray();
              var parametersString = CalculateSignatureBaseString(allParameters);
              var signatureBaseString = OAuth1aUtil.CalcualteSignatureBaseString(method, uri, parametersString);
              var sigingKey = GetSigningKey(consumerSecret, tokenSecret);
              var signature = Sign(signatureBaseString, sigingKey);
              return signature;
          }
      

      提出请求

      现在您只需要创建一个有效的http请求,并将oauth参数作为“授权”标题添加到请求中。