0

这是我到目前为止所拥有的,但它不起作用,因为我不明白 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();
        }
    }
}
4

1 回答 1

3

您的实际问题应该类似于“是否可以使用 DotNetOpenAuth 来签署带有或不带有访问令牌的请求?”,回答这个问题我应该说我不知道​​,甚至我无法通过阅读 DotNetOpenAuth 代码库找到它.

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

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

但是要发出签名请求,您需要遵循一个简单的过程:

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

收集请求参数

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

在 OAuth 特定参数中nonce,这是可用于生成 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. 通过使用签名密钥对签名基本字符串进行签名来创建签名

要计算签名基本字符串,您需要首先将所有参数连接成一个字符串,然后百分比对整个字符串进行编码。这是帮助您进行百分比编码的代码:

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));
}

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

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;
}

让我们将上面的字符串称为“参数字符串”。然后要计算签名基本字符串,您只需使用“&”将请求的 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 : "");
}

在您的情况下,要发出签名请求,您只需要传递nullOAuthTokenSecret 参数的值。

好的,现在您有了一个签名基字符串,您现在需要做的就是使用 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 参数作为“授权”标头添加到请求中。

于 2012-09-18T06:49:26.440 回答