Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Twitter OAuth / 7 сообщений из 7, страница 1 из 1
22.02.2010, 17:33
    #36483260
BOBAH13
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Twitter OAuth
Добрый день.
Суть вопроса в том, что никак не могу пройти авторизацию, а именно request_token. Т.е. самый первый шаг.
Прошу помощи и взгляда из стороны, так сказать.

Модуль для формирования запроса OAuth тянул уже не помню откуда, а формирую так (constumer key & secret они вбиты, и взяты из моего приложения на твиттере)

Модуль
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
public class OAuthBase
    {
        public static long CreateTimestamp()
        {
            var now = DateTime.UtcNow;
            var then = new DateTime( 1970 ,  1 ,  1 );
            var timespan = (now - then);
            var timestamp = (long)timespan.TotalSeconds;
            return timestamp;
        }

        private const string ALPHANUMERIC = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        public static string CreateNonce()
        {
            var sb = new StringBuilder();
            var random = new Random();
            for (var i =  0 ; i <=  12 ; i++)
            {
                var index = random.Next(ALPHANUMERIC.Length);
                sb.Append(ALPHANUMERIC[index]);
            }
            return sb.ToString();
        }

        public static string NormalizeUrl(string url)
        {
            Uri uri;
            // only work with a valid URL in lowercase
            if (Uri.TryCreate(url, UriKind.Absolute, out uri))
            {
                // only include non-standard ports
                string port = "";
                if (uri.Scheme.Equals("http") && uri.Port !=  80  ||
                   uri.Scheme.Equals("https") && uri.Port !=  443  ||
                   uri.Scheme.Equals("ftp") && uri.Port !=  20 )
                {
                    port = ":" + uri.Port;
                }
                // use only the scheme, host, port, and path
                url = uri.Scheme + "://" + uri.Host + port + uri.AbsolutePath;
            }
            return url;
        }

        public static string NormalizeRequestParameters(NameValueCollection parameters)
        {
            var sb = new StringBuilder();
            var list = new List<NameValuePair>();
            foreach (var name in parameters.AllKeys)
            {
                // escaping occurs both here, and during concatenation
                var value = Uri.EscapeDataString(parameters[name]);
                var item = new NameValuePair { Name = name, Value = value };

                // Ensure duplicates are not included
                if (list.Contains(item))
                {
                    throw new ArgumentException("Cannot add duplicate parameters");
                }
                list.Add(item);
            }
            list.Sort((left, right) =>
                {
                    if (left.Name.Equals(right.Name))
                    {
                        return left.Value.CompareTo(right.Value);
                    }
                    return left.Name.CompareTo(right.Name);
                });
            foreach (var item in list)
            {
                sb.Append(item.Name + "=" + item.Value);
                if (list.IndexOf(item) < list.Count -  1 )
                {
                    sb.Append("&");
                }
            }
            return sb.ToString();
        }

        private class NameValuePair
        {
            public string Name { get; set; }
            public string Value { get; set; }

            public bool Equals(NameValuePair other)
            {
                return Equals(other.Name, Name) &&
                       Equals(other.Value, Value);
            }

            public override bool Equals(object obj)
            {
                return Equals((NameValuePair)obj);
            }

            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        }

        public static string ConcatenateRequestElements(string method, string url, string parameters)
        {
            // URL encode base elements
            url = Uri.EscapeDataString(url);
            parameters = Uri.EscapeDataString(parameters);

            // build signature base according to spec
            var sb = new StringBuilder();
            sb.Append(method.ToUpper()).Append("&");
            sb.Append(url).Append("&");
            sb.Append(parameters);

            return sb.ToString();
        }

        public static string CreateSignature(string signatureBase, string consumerSecret, string tokenSecret)
        {
            if (tokenSecret == null)
            {
                // the token secret is unknown
                tokenSecret = string.Empty;
            }

            // URL encode key elements
            consumerSecret = Uri.EscapeDataString(consumerSecret);
            tokenSecret = Uri.EscapeDataString(tokenSecret);

            // initialize the cryptography provider
            var key = String.Concat(consumerSecret, "&", tokenSecret);
            var keyBytes = Encoding.ASCII.GetBytes(key);
            var signatureMethod = new HMACSHA1(keyBytes);

            // create a signature with the base and provider
            var data = Encoding.ASCII.GetBytes(signatureBase);
            var hash = signatureMethod.ComputeHash(data);
            var signature = Convert.ToBase64String(hash);

            // You must encode the URI for safe net travel
            signature = Uri.EscapeDataString(signature);
            return signature;
        }
    }

Мой код
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
public enum Method { GET, POST };
        public string OAuthWebRequest(Method method, string url, string postData)
        {
            var timestamp = OAuthBase.CreateTimestamp().ToString(); // тут все ок, фомируется
            var nonce = OAuthBase.CreateNonce(); // аналогично
            var oauthParameters = new NameValueCollection
            {
                {"oauth_timestamp", timestamp},
                {"oauth_nonce", nonce},
                {"oauth_version", "1.0"},
                {"oauth_signature_method", "HMAC-SHA1"},
                {"oauth_consumer_key", ConsumerKey}
            };

            url = OAuthBase.NormalizeUrl(url);
            var parameters = OAuthBase.NormalizeRequestParameters(oauthParameters);
            var signatureBase = OAuthBase.ConcatenateRequestElements(method.ToString(), url, parameters);

            var signature = OAuthBase.CreateSignature(signatureBase, ConsumerSecret, TokenSecret); // разумеется сейчас TokenSecret = string.emty, но это так и должно быть.
            oauthParameters.Add("oauth_signature", signature);

            var header = new StringBuilder();
            header.Append("OAuth realm=\"\", ");
            for (var i =  0 ; i < oauthParameters.Count; i++)
            {
                var key = oauthParameters.GetKey(i);
                var pair = key + "=\"" + oauthParameters[key] + "\"";
                header.Append(pair);
                if (i < oauthParameters.Count -  1 )
                {
                    header.Append(", ");
                }
            }

            System.Net.ServicePointManager.Expect100Continue = false;
            var request = (HttpWebRequest)WebRequest.Create(url); // просто перенаправил вбитый url
            request.Headers["Authorization"] = header.ToString(); // ну вроде бы, с виду, все идеально
            request.Method = method.ToString();
            if (method == Method.POST) // можно не рассматривать, мы шлем GET запрос
            {
                request.ContentType = "application/x-www-form-urlencoded";
                StreamWriter requestWriter = new StreamWriter(request.GetRequestStream());
                try { requestWriter.Write(postData); }
                catch { throw; }
                finally
                {
                    requestWriter.Close();
                    requestWriter = null;
                }
            }

            WebResponse response = request.GetResponse();
            /* тут забираем нашу ошибку:
                   Удаленный сервер возвратил ошибку: (401) Несанкционированный.
                   В дополнение возвращает - Failed to validate oauth signature and token
            */
            StreamReader responseReader = new StreamReader(response.GetResponseStream());
            var responseData = responseReader.ReadToEnd();
            response.Close();
            responseReader.Close();
            responseReader = null;
            request = null;
            return responseData;
        }

        public void SignIn()
        {
           string response = OAuthWebRequest(Method.GET, "http://twitter.com/oauth/request_token", string.Empty);
}

Т.е. как видим, все принципе верно, но ошибка удивляет меня, и понять что не так не могу никак.
1. Модуль публикуется прямо на офф сайте OAuth, т.е. видимо верить можно
2. Ну Consumer Key + Secret - так же верны, ведь с twitter.com беру их.
3. Т.е. формирую запрос не верно, но где проблема, грабли то ?

Спасибо. и очень надеюсь, что все-таки кто-то рассмотрит данный вопрос (думаю многие с .NET имели(имеют) дело с OAuth ?!
...
Рейтинг: 0 / 0
22.02.2010, 18:43
    #36483385
Silverlight
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Twitter OAuth
Это связано с междоменной политикой. На Твиттере разрешены только вызовы из своего домена(*.twitter.com), a в SL запрещены междоменные POST. Нужно создать у себя прокси сервис на сервере и через него общаться. Есть масса готовых примеров с исходниками, скачай и посмотри.
...
Рейтинг: 0 / 0
22.02.2010, 19:21
    #36483451
BOBAH13
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Twitter OAuth
Спасибо за отзывчивость. Честно говоря я не понял, где и что создавать, и зачем. Подобного не видел в указаниях Twitter API. Можете прокомментировать или ссылки кинуть какие либо ?
Спасибо.
...
Рейтинг: 0 / 0
22.02.2010, 19:37
    #36483480
Silverlight
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Twitter OAuth
Создавать нужно свой WCF сервис, который будет работать с twitter
...
Рейтинг: 0 / 0
23.02.2010, 00:08
    #36483852
Silverlight
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Twitter OAuth
Файл междоменной политики twitter
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
<?xml version="1.0" encoding="UTF-8" ?> 
<cross-domain-policy  
  xmlns:xsi=http://www.w3.org/ 2001 /XMLSchema-instance xsi:
  noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/ 
  PolicyFile.xsd">
  <allow-access-from domain="*.twitter.com" /> 
  <site-control permitted-cross-domain-policies="master-only" /> 
  <allow-http-request-headers-from domain="*.twitter.com" /> 
</cross-domain-policy>
...
Рейтинг: 0 / 0
23.02.2010, 03:53
    #36483932
WCF
WCF
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Twitter OAuth
google: twitter wcf

первые 3 ссылки весьма позновательные. Там создаётся клиент. Нужно просто переделать его в промежуточный сервис.
...
Рейтинг: 0 / 0
23.02.2010, 08:33
    #36483968
BOBAH13
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Twitter OAuth
Спасибо ребят. Пока сделал request на Basic аунтификации, попробую с WCF и OAuth, хотя всеравно странно как то выходит, Basic работает, а OAuth нет.
Ну поживем увидим.
...
Рейтинг: 0 / 0
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Twitter OAuth / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]