IIJIMASが勉強しようとしています。

これからこれから♪

目次

Blog 利用状況

ニュース

共著:




わんくま同盟 東京勉強会 #99 私の資料

個数を数えてみたい!

わんくま同盟 東京勉強会 #91 私の資料

きっと楽しいトポロジー

わんくま同盟 東京勉強会 #45 数学デー 私の資料(pptxとxlsx)

確率の不思議

わんくま同盟 東京勉強会 #37 私のLT資料

数の冪の和の式 を求めてみよう!

デブサミ09でわんくま同盟の紹介をしたスライド

わんくま同盟 東京勉強会 #26 LT祭りの私のスライド

わんくま同盟 東京勉強会 #23の私のスライド

わんくま同盟 東京勉強会 #18の私のスライド


自己紹介(仮)

IIJIMASと申します。
東京都多摩市在住です。多摩川のそばです。
猫好きです。
IIJIMASのSは何って言われます。 IIJIMASって
なんて読むかは自由です。
魚や網間企業とゲームとは無関係です。
数学とか宇宙とかの読み物とか好きです。
血液型:果汁100%A
メタボ予備軍。。。orz
Twitter

...............
MVP 審査応募ページ~ 求む、日本のMVP。
MCTS:.NET Framework 2.0: Windows アプリケーション
MCTS:.NET Framework 2.0: Windows アプリケーション

MCSD.NET:マイクロソフト認定ソリューションデベロッパー(MCSD) Microsoft .NET トラック
Microsoft Certified Solution Developer for Microsoft.NET

リンク

わんくま同盟
わんくま同盟

C#VB.NET掲示板
C#VB.NET掲示板

わんくま同盟 Blog's

ちょっと一言(仮)


書庫

日記カテゴリ

自作TwitterクライアントをOAuth認証に対応させる。(2)

自作TwitterクライアントをOAuth認証に対応させる。の続き。

  1. クライアントがTwitterにRequest Tokenを要求する。
  2. TwitterがクライアントにRequest Tokenを返す。
  3. ユーザにAuthorizeページでクライアントアプリケーションを「許可」してもらう。
  4. Twitterが暗証番号を表示する。
  5. ユーザがクライアントに暗証番号を入力する。
  6. クライアントがTwitterにAccess Tokenを要求する。
  7. TwitterがクライアントにAccess Tokenを返す。
  8. クライアントにAccess TokenとAccess TokenSecretを保存する。
  9. 以降、クライアントはAccess Tokenを含めてAPIの各リクエストをする。

各手順では細かいパラメータがあります。このうちクライアントに関連づける必須のパラメータConsumer keyと対になるConsumer Secretを取得するためにクライアント開発者はいかのページアクセスしてフォームを埋める必要があります。
「Twitter / Applications: Register」 http://twitter.com/apps/new

Application Name:にアプリケーション名(twitterという文字列を含むことができません!)を入力、Description:に説明(10文字以上)を入力します。Application Website:は必須の項目になっていますので、今回は自分のホームページを設定します。公開クライアントの場合はクライアントのダウンロードサイトやサポートサイト等を指定します。Application Type:はデスクトップアプリケーションの場合Clientを選択します。

これらはあとからでも修正できます。

入力を終え[Save]をクリックすると、Consumer key と Consumer secret の値が表示されます。アプリケーションの端末に保存して使用します。

自分のアプリは複数登録できて、以下のページより入力した情報の確認と修正が行えます。
[Link]「Twitter / Applications」 http://twitter.com/apps

あとは実装です。私の自作クライアントはC#を使用していましたので、「Twitter API Wiki / OAuth Examples」 のリンク先の.NETのさらにリンク先などを参考にしました。それ以外にもすでにいろいろなところでライブラリやサンプルも提供されているようですが、勉強も兼ねてそれらを参考にあえて自分でライブラリ部分もコーディングしました。アプリケーションは公開しませんが、改めて作成して、ライブラリ部分のコードの主要部分をこちらに公開しようかと思います。


Const.cs(定数クラス、IntelliSenseを使いたいだけです()

 

namespace TwitterUtils

{

    /// <summary>

    /// constant

    /// </summary>

    public static class Const

    {

        //URL

        public const string URL_TWITTER = "http://twitter.com/";

        public const string URL_API_TWITTER = "http://api.twitter.com/";

        public const string URL_API_TWITTER_1 = "http://api.twitter.com/1/";

        //API

        public const string API_REQUEST_TOKEN = URL_API_TWITTER + "oauth/request_token";

        public const string API_AUTHORIZE = URL_API_TWITTER + "oauth/authorize";

        public const string API_ACCESS_TOKEN = URL_API_TWITTER + "oauth/access_token";

        public const string API_STATUSES = URL_API_TWITTER_1 + "statuses/";

        //API_METHOD

        public const string API_METHOD_PUBLIC_TIMELINE = "public_timeline";

        public const string API_METHOD_HOME_TIMELINE = "home_timeline";

        public const string API_METHOD_FRIENDS_TIMELINE = "friends_timeline";

        public const string API_METHOD_USER_TIMELINE = "user_timeline ";

        public const string API_METHOD_MENTIONS = "mentions";

        public const string API_METHOD_FRIENDS = "friends";

        public const string API_METHOD_FOLLOWERS = "followers";

        public const string API_METHOD_SHOW = "show";

        public const string API_METHOD_UPDATE = "update";

        public const string API_METHOD_DESTROY = "destroy  ";

        public const string API_METHOD_RETWEET = "retweet";

        public const string API_METHOD_RETWEETS = "retweets";

 

        //FORMAT

        public const string FORMAT_XML = ".xml";

        public const string FORMAT_JSON = ".json";

        public const string FORMAT_ATOM = ".atom";

        public const string FORMAT_RSS = ".rss";

 

        //URL query parameter

        public const string QUERY_OAUTH_CONSUMER_KEY = "oauth_consumer_key";

        public const string QUERY_OAUTH_NONCE = "oauth_nonce";

        public const string QUERY_OAUTH_SIGNATURE_METHOD = "oauth_signature_method";

        public const string QUERY_OAUTH_TOKEN = "oauth_token";

        public const string QUERY_OAUTH_TOKEN_SECRET = "oauth_token_secret";

        public const string QUERY_OAUTH_TIMESTAMP = "oauth_timestamp";

        public const string QUERY_OAUTH_VERSION = "oauth_version";

        public const string QUERY_OAUTH_SIGNATURE = "oauth_signature";

        public const string QUERY_OAUTH_VERIFIER = "oauth_verifier";

 

        public const string QUERY_STATUS = "status";

        public const string QUERY_IN_REPLY_TO_STATUS_ID = "in_reply_to_status_id";

        //constant values

        public const string VALUE_OAUTH_VERSION = "1.0";

        public const string VALUE_HMAC_SHA1 = "HMAC-SHA1";

        public const string HTTPMETHOD_GET = "GET";

        public const string HTTPMETHOD_POST = "POST";

    }

}

 


BasicUtil.cs (名前をBasicUtilという名前にしましたが、Basic認証とは何の関係もありません。単なる文字列操作のメソッドです。)

 

 

namespace TwitterUtils

{

    using System;

    using System.Collections.Generic;

    using System.Text;

    /// <summary>

    /// Util methods

    /// </summary>

    public static class BasicUtil {

        /// <summary>

        /// UrlEncode

        /// </summary>

        /// <param name="src">string</param>

        /// <returns>encoded string</returns>

        public static string UrlEncode(string src)

        {

            string escaped = Uri.EscapeDataString(src);

 

            StringBuilder sb = new StringBuilder(escaped.Length);

            foreach (var c in escaped)

            {

                if (c <= 0x2A && "!&'()*".IndexOf(c) > -1)

                {

                    sb.AppendFormat("%{0:X2}", (int)c);

                }

                else

                {

 

                    sb.Append(c);

                }

            }

            return sb.ToString();

        }

        /// <summary>

        /// IDictionary<string,string> object => Url query string

        /// </summary>

        /// <param name="dic">IDictionary<string,string> object</param>

        /// <returns>Url query string</returns>

        public static string BuildQueryString(IDictionary<string, string> dic)

        {

            StringBuilder sb = new StringBuilder();

            foreach (var item in dic)

            {

                sb.Append(item.Key).Append('=').Append(item.Value);

                sb.Append('&');

            }

            sb.Remove(sb.Length - 1, 1);

            return sb.ToString();

        }

        /// <summary>

        /// Url query string => IDictionary<string,string> object 

        /// </summary>

        /// <param name="queryString">Url query string</param>

        /// <returns>IDictionary<string,string>IDictionary object</returns>

        public static IDictionary<string, string> QueryStringToDictionary(string queryString)

        {

            queryString = queryString.Trim('?');

            var dic = new Dictionary<string, string>();

            if (!string.IsNullOrEmpty(queryString))

            {

                string[] qs = queryString.Split('&');

                foreach (var item in qs)

                {

                    string[] nv = item.Split('=');

                    dic.Add(nv[0], nv[1]);

                }

            }

            return dic;

        }

    }

  

}

 


OAuthUtil.cs (OAuth認証の各手順で使用する値の計算メソッド群です。)

 

 

namespace TwitterUtils

{

    using System;

    using System.Text;

    using System.Security.Cryptography;

    /// <summary>

    /// Utility methods for OAuth

    /// </summary>

    public static class OAuthUtil

    {

        static Random random = new Random(Environment.TickCount);

        /// <summary>

        /// Hash method using HMACSHA1

        /// </summary>

        /// <param name="keyBytes">key</param>

        /// <param name="dataBytes">data</param>

        /// <returns>result</returns>

        public static byte[] ComputeHash(byte[] keyBytes, byte[] dataBytes)

        {

            HMACSHA1 hmacsha1 = new HMACSHA1();

            hmacsha1.Key = keyBytes;

            byte[] resultBytes = hmacsha1.ComputeHash(dataBytes);

            return resultBytes;

        }

        /// <summary>

        /// Hash method using HMACSHA1

        /// </summary>

        /// <param name="keyString">key string</param>

        /// <param name="dataString">data string</param>

        /// <param name="enc">encoding (from string  to byte)</param>

        /// <returns>result string</returns>

        public static string ComputeHash(string keyString, string dataString, Encoding enc)

        {

            byte[] keyBytes = enc.GetBytes(keyString);

            byte[] dataBytes = enc.GetBytes(dataString);

            return Convert.ToBase64String(ComputeHash(keyBytes, dataBytes), Base64FormattingOptions.None);

        }

        /// <summary>

        /// TIME Stamp

        /// </summary>

        /// <returns>TIME Stamp</returns>

        public static string GetTimeStamp()

        {

            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);

            return Convert.ToInt64(ts.TotalSeconds).ToString();

        }

        /// <summary>

        /// random integer between 123400 - 9999999

        /// </summary>

        /// <returns>random integer string</returns>

        public static string GetNonce()

        {

            return random.Next(123400, 9999999).ToString();

        }

 

    }

 

}

 


OAuthURLBuilder.csOAuth認証で使用するURLを組み立てるメソッドがあります。tokentoken_secret等を保持させるのでインスタンス化が可能なクラスにしました。)

 

 

namespace TwitterUtils

{

    using System.Collections.Generic;

    using System.Text;

    /// <summary>

    ///  OAuth URL methods

    /// </summary>

    public class OAuthURLBuilder

    {

        string oauth_consumer_key;

        string oauth_consumer_secret;

        string oauth_token;

        string oauth_token_secret;

        /// <summary>

        /// constractor

        /// </summary>

        /// <param name="oauthConsumerKey">oauthConsumerKey</param>

        /// <param name="oauthConsumerSecret">oauthConsumerSecret</param>

        public OAuthURLBuilder(string oauthConsumerKey, string oauthConsumerSecret)

        {

            oauth_consumer_key = oauthConsumerKey;

            oauth_consumer_secret = oauthConsumerSecret;

            oauth_token = "";

            oauth_token_secret = "";

        }

        /// <summary>

        /// sets OAuth token

        /// </summary>

        /// <param name="token">OAuth token</param>

        /// <returns>OAuthURLBuilder object</returns>

        public OAuthURLBuilder SetOAuthToken(string token)

        {

            oauth_token = token;

            return this;

        }

        /// <summary>

        /// sets OAuth tokenSecret

        /// </summary>

        /// <param name="tokenSecret">OAuth tokenSecret</param>

        /// <returns>OAuthURLBuilder object</returns>

        public OAuthURLBuilder SetOAuthTokenSecret(string tokenSecret)

        {

            oauth_token_secret = tokenSecret;

            return this;

        }

        /// <summary>

        /// Gets Signature

        /// </summary>

        private static string GetSignature(string httpMethod, string url, string queries, string consumerSecret, string tokenSecret)

        {

            string sigData = string.Format("{0}&{1}&{2}", httpMethod, BasicUtil.UrlEncode(url), BasicUtil.UrlEncode(queries));

            string sigKey = string.Format("{0}&{1}", BasicUtil.UrlEncode(consumerSecret), BasicUtil.UrlEncode(tokenSecret));

            return OAuthUtil.ComputeHash(sigKey, sigData, Encoding.UTF8);

        }

        /// <summary>

        /// get twitter API Url with OAuth

        /// </summary>

        /// <param name="httpMethod">Http method (GET/POST)</param>

        /// <param name="originalUrl">Original Url</param>

        /// <param name="queries">url queries</param>

        /// <returns>twitter API Url with OAuth</returns>

        public string GetURL(string httpMethod, string originalUrl, IDictionary<string, string> queries)

        {

            var paramsDic = GetDictionaryWithOAuthParams();

            foreach (var en in queries)

            {

                paramsDic.Add(en.Key, en.Value);

            }

            if (!string.IsNullOrEmpty(oauth_token))

            {

                paramsDic.Add(Const.QUERY_OAUTH_TOKEN, oauth_token);

            }

 

            string queryString = BasicUtil.BuildQueryString(paramsDic);

            string signature = GetSignature(httpMethod, originalUrl, queryString, oauth_consumer_secret, oauth_token_secret);

            paramsDic.Add(Const.QUERY_OAUTH_SIGNATURE, BasicUtil.UrlEncode(signature));

            return string.Format("{0}?{1}", originalUrl, BasicUtil.BuildQueryString(paramsDic));

        }

        /// <summary>

        /// Gets DictionaryWithOAuthParams

        /// </summary>

        private SortedDictionary<string, string> GetDictionaryWithOAuthParams()

        {

            return new SortedDictionary<string, string> {

                                                    { Const.QUERY_OAUTH_CONSUMER_KEY, oauth_consumer_key },

                                                    { Const.QUERY_OAUTH_NONCE, OAuthUtil.GetNonce()},

                                                    { Const.QUERY_OAUTH_SIGNATURE_METHOD, Const.VALUE_HMAC_SHA1 },

                                                    { Const.QUERY_OAUTH_TIMESTAMP, OAuthUtil.GetTimeStamp() },

                                                    { Const.QUERY_OAUTH_VERSION, Const.VALUE_OAUTH_VERSION },

                                                };

        }

        /// <summary>

        /// gets RequestTokenURL

        /// </summary>

        /// <returns>RequestTokenURL</returns>

        public string GetRequestTokenURL()

        {

            return GetURL(

                Const.HTTPMETHOD_GET,

                Const.API_REQUEST_TOKEN,

                new Dictionary<string, string>());

        }

        /// <summary>

        /// gets AccessTokenURL

        /// </summary>

        /// <param name="pin">pin number</param>

        /// <returns>AccessTokenURL</returns>

        public string GetAccessTokenURL(string pin)

        {

            return GetURL(

                Const.HTTPMETHOD_GET,

                Const.API_ACCESS_TOKEN,

                new Dictionary<string, string>() { { Const.QUERY_OAUTH_VERIFIER, pin } });

        }

 

 

        /// <summary>

        /// Gets AuthorizeURL

        /// </summary>

        /// <returns>Authorize page URL</returns>

        public string GetAuthorizeURL()

        {

            var queries = new Dictionary<string, string>() { { Const.QUERY_OAUTH_TOKEN, oauth_token } };

            return string.Format("{0}?{1}", Const.API_AUTHORIZE, BasicUtil.BuildQueryString(queries)); ;

        }

    }

}

 


 

  で、これらを使用するコードMain()の含まれるコードなのですが、長くなりましたのでまた後のエントリにします。

投稿日時 : 2010年8月1日 23:56

コメントを追加

# re: 自作TwitterクライアントをOAuth認証に対応させる。(2) 2010/08/02 10:36 trapemiya

いつかはtwitter関連のアプリを作る時が来そうな気がしてますので、こういう情報はとても助かります。

# re: 自作TwitterクライアントをOAuth認証に対応させる。(2) 2010/08/02 20:12 テック

はじめまして、私テックと申します。
以後よろしくお願いします。

私もOAuth認証に対応する
プラグインを作成しようと思い、
書籍など参考にしていましたが、
分かりにくかったので、
具体的に実装されているコードがあり、
とても助かりました。

私も記事の内容を参考にし、
コーディングしてみようと思います。
以上、失礼します。

# re: 自作TwitterクライアントをOAuth認証に対応させる。(2) 2010/08/11 21:52 IIJIMAS

trapemiyaさんコメントありがとうございます!

>いつかはtwitter関連のアプリを作る時が来そうな気がしてます

作りましょう作りましょう!

>情報はとても助かります。

そういっていただけると嬉しいですありがとうございます!

# re: 自作TwitterクライアントをOAuth認証に対応させる。(2) 2010/08/11 21:55 IIJIMAS

はじめまして、テックさん
テックさんコメントありがとうございます。

>具体的に実装されているコードがあり、
>とても助かりました。

そういっていただけると嬉しいです!ありがとうございます!

タイトル  
名前  
URL
コメント