[解決済み] .NETでの検証付きOAuth
質問
私は、OAuth 対応のアプリケーション、特に Mendeley (現在はコンソール アプリとして使用しています) と統合するための .NET ベースのクライアント アプリを (WPF で) 作成しようとしています。 http://dev.mendeley.com ) と統合します。
OAuth を使用するのは初めてですが、使い始めるのにかなり苦労しています。いくつかの .NET OAuth ライブラリまたはヘルパーを見つけましたが、それらは私が必要と思うより複雑なようです。私がしたいことは、Mendeley APIにRESTリクエストを発行し、応答を取得することです!
今のところ、私は試してみました。
- DotNetOpenAuth
- http://github.com/bittercoder/DevDefined.OAuth
- http://oauth.googlecode.com/svn/code/csharp/
最初のもの (DotNetOpenAuth) は、私が何時間もかけて方法を見つけ出そうとすれば、必要なことができるように思えるのです。2番目と3番目は、私が知る限り、Mendeley が送り返す検証コードをサポートしていません。)
私はMendeleyからコンシューマーキーとシークレットを入手し、DotNetOpenAuthで、ユーザーがアプリケーションに入力するための検証コードを提供するMendeleyページでブラウザを起動させることに成功しました。しかし、この時点で迷子になり、アプリケーションに戻る検証コードを賢明に提供する方法を見つけることができませんでした。
私は、どこから始めればよいのか全くわからないことを喜んで認めます (かなり急な学習曲線があるように見えますが)。
どのように解決するのですか?
私はあなたに同意します。 .NET アプリで利用できるオープンソースの OAuth サポート クラスは、理解しにくい、過度に複雑 (DotNetOpenAuth が公開しているメソッドはいくつあるか)、お粗末 (あなたが提供した google リンクから OAuthBase.cs モジュールの 10 の文字列パラメーターのメソッドをご覧ください - 状態管理がまったくありません)、またはその他不満な点ばかりです。
こんなに複雑である必要はないのです。
私はOAuthの専門家ではありませんが、OAuthクライアントサイドマネージャークラスを作成し、TwitterとTwitPicでうまく使っています。 使用方法は比較的簡単です。オープンソースで、ここから入手できます。 Oauth.cs
おさらいですが、OAuth 1.0aでは...ちょっと面白いことに、特別な名前があって、"standard"のように見えますが、私が知る限り、"OAuth 1.0a" を実装するサービスはTwitterのみです。 標準なんだろうけど 十分 OAuth 1.0aでは、以下のように動作します。 デスクトップアプリケーションの場合 はこうです。
-
アプリの開発者であるあなたは、アプリを登録し、"consumer key" と "consumer secret" を取得します。 Arstechnicaでは なぜこのモデルがベストではないのかについて、よく書かれた分析があります。 しかし、よく言われるように それはそれである .
-
アプリが実行されます。初回実行時には、アプリがTwitterとその姉妹サービス(TwitPicなど)に対して自動認証のRESTリクエストを行うことについて、ユーザーから明示的に承認を得る必要があります。これを行うには、ユーザーによる明示的な承認を含む承認プロセスを経る必要があります。これは、アプリを最初に実行するときにのみ発生します。 このように
- リクエストトークンを要求します。 別名、テンポラリートークン。
- クエリパラメータとしてリクエストトークンを渡し、Web ページをポップします。 このWebページでは、ユーザーにUIを提示し、「このアプリへのアクセスを許可しますか」と尋ねます。
- ユーザーは twitter の Web ページにログインし、アクセスを許可または拒否します。
- 応答HTMLページが表示されます。 ユーザーがアクセスを許可した場合、48ptのフォントでPINが表示されます。
- ユーザーは、その PIN を Windows のフォーム ボックスに切り取り/貼り付け、"Next" または同様のものをクリックする必要があります。
- デスクトップ アプリは、quot;Access token" のための自動認証要求を行います。 別の REST リクエストです。
- デスクトップアプリは、アクセストークンとアクセシークレットを受け取ります。
承認ダンス後、デスクトップ アプリは、ユーザー固有のアクセストークンとアクセストークン (アプリ固有のコンシューマー キーとコンシューマー シークレット) を使用して、ユーザーに代わって Twitter に認証済みリクエストを行うことができます。 これらは有効期限はありませんが、ユーザーがアプリの認証を解除した場合、Twitterが何らかの理由でアプリの認証を解除した場合、またはアクセストークンやシークレットを紛失した場合は、再び承認作業を行う必要があります。
巧妙でない場合、UI フローは複数ステップの OAuth メッセージ フローをミラーリングするようなものです。 もっと良い方法があります。
WebBrowser コントロールを使用し、デスクトップ アプリ内で認証 Web ページを開きます。 ユーザーが [許可] をクリックすると、WebBrowser コントロールから応答テキストを取得し、PIN を自動的に抽出して、アクセストークンを取得します。 5~6回のHTTPリクエストを送信しますが、ユーザーが見る必要があるのは、1つのAllow/Denyダイアログだけです。 シンプルですね。
このように
UI を整理した場合、残る唯一の課題は oauth で署名されたリクエストを作成することです。 oauth署名の要件は特殊なので、これは多くの人をつまずかせます。これは簡略化されたOAuth Managerクラスが行うことです。
トークンを要求するコード例です。
var oauth = new OAuth.Manager();
// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
oauth["consumer_key"] = MY_APP_SPECIFIC_KEY;
oauth["consumer_secret"] = MY_APP_SPECIFIC_SECRET;
oauth.AcquireRequestToken(rtUrl, "POST");
これでおしまい . シンプルですね。 コードからわかるように、oauthパラメータにアクセスする方法は、文字列ベースのインデクサ、つまり辞書のようなものを経由しています。 AcquireRequestTokenメソッドは、リクエストトークン(別名、一時的なトークン)を付与するサービスのURLに、oauth署名付きのリクエストを送信します。 Twitterの場合、このURLは" https://api.twitter.com/oauth/request_token です。 です。oauth 仕様では、一連の oauth パラメータ (token, token_secret, nonce, timestamp, consumer_key, version, and callback) を特定の方法 (url-encoded and joined by ampersand) で辞書順にまとめ、その結果に対して署名を生成し、同じパラメータと署名とを別の方法 (joined by commas) で新しい oauth_signature パラメータに格納する必要があると述べています。 OAuthマネージャクラスは、あなたのためにこれを自動的に行います。 これはnoncesとタイムスタンプとバージョンを生成します。 と署名 を自動的に生成します。あなたのアプリはそのようなものを気にしたり、意識したりする必要はありません。 oauth パラメータの値を設定し、シンプルなメソッドを呼び出すだけです。マネージャクラスはリクエストを送信し、あなたのためにレスポンスを解析します。
OK, then what? リクエストトークンを取得したら、WebブラウザのUIをポップアップして、ユーザーが明示的に承認を与えるようにします。正しく実行すれば、埋め込みブラウザーでこれをポップアップします。 Twitter の場合、このための URL は " です。 https://api.twitter.com/oauth/authorize?oauth_token= となり、oauth_tokenが付加されます。これをコードで以下のようにします。
var url = SERVICE_SPECIFIC_AUTHORIZE_URL_STUB + oauth["token"];
webBrowser1.Url = new Uri(url);
(これを外部ブラウザで行う場合は
System.Diagnostics.Process.Start(url)
.)
Urlプロパティを設定すると、WebBrowserコントロールは自動的にそのページに移動するようになります。
ユーザーが "Allow"ボタンをクリックすると、新しいページがロードされます。これはHTMLフォームで、フルブラウザと同じように動作します。コード内で、WebBrowserコントロールのDocumentedCompletedイベントに対するハンドラを登録し、そのハンドラ内で、ピンを取得します。
var divMarker = "<div id=\"oauth_pin\">"; // the div for twitter's oauth pin
var index = webBrowser1.DocumentText.LastIndexOf(divMarker) + divMarker.Length;
var snip = web1.DocumentText.Substring(index);
var pin = RE.Regex.Replace(snip,"(?s)[^0-9]*([0-9]+).*", "$1").Trim();
HTMLのスクリーンスクレイピングの一種です。
ピンを掴んだら、もうWebブラウザは必要ありませんから。
webBrowser1.Visible = false; // all done with the web UI
...そして、これに対してDispose()も呼び出したいかもしれません。
次のステップでは、ピンとともに別のHTTPメッセージを送信して、アクセストークンを取得します。 これは別の署名付き oauth 呼び出しで、上で説明した oauth の順序と形式を使用して構築されます。しかし、もう一度言いますが、OAuth.Manager クラスを使用すれば、これは本当に簡単です。
oauth.AcquireAccessToken(URL_ACCESS_TOKEN,
"POST",
pin);
Twitterの場合、そのURLは"です。 https://api.twitter.com/oauth/access_token となります。
これでアクセストークンが手に入ったので、署名付き HTTP リクエストで使用できるようになりました。 このように
var authzHeader = oauth.GenerateAuthzHeader(url, "POST");
...ここで
url
はリソースのエンドポイントです。ユーザーのステータスを更新するには、"となります。
http://api.twitter.com/1/statuses/update.xml?status=Hello
"となります。
というHTTPヘッダにその文字列を設定します。 認証 .
TwitPic のようなサードパーティーのサービスとやりとりするためには、TwitPic のようなサードパーティーのサービスに対して 若干異なる OAuthヘッダーを作成する必要があります。
var authzHeader = oauth.GenerateCredsHeader(URL_VERIFY_CREDS,
"GET",
AUTHENTICATION_REALM);
Twitterの場合、verify creds urlとrealmの値は"です。 https://api.twitter.com/1/account/verify_credentials.json "、および " http://api.twitter.com/ "それぞれです。
...そして その という HTTP ヘッダに認可文字列を記述します。 X-Verify-Credentials-Authorization」と呼ばれるHTTPヘッダで指定します。 . そして、それをTwitPicのようなサービスに、送信しているリクエストと一緒に送信します。
これで完了です。
全部合わせると、twitterのステータスを更新するコードはこんな感じでしょうか。
// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
var oauth = new OAuth.Manager();
// The consumer_{key,secret} are obtained via registration
oauth["consumer_key"] = "~~~CONSUMER_KEY~~~~";
oauth["consumer_secret"] = "~~~CONSUMER_SECRET~~~";
oauth.AcquireRequestToken(rtUrl, "POST");
var authzUrl = "https://api.twitter.com/oauth/authorize?oauth_token=" + oauth["token"];
// here, should use a WebBrowser control.
System.Diagnostics.Process.Start(authzUrl); // example only!
// instruct the user to type in the PIN from that browser window
var pin = "...";
var atUrl = "https://api.twitter.com/oauth/access_token";
oauth.AcquireAccessToken(atUrl, "POST", pin);
// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
MessageBox.Show("There's been a problem trying to tweet:" +
Environment.NewLine +
response.StatusDescription);
}
OAuth 1.0a はちょっと複雑な仕組みになっていますが、それを使う必要はありません。 OAuth.Manager は発信される oauth リクエストの生成と、レスポンスに含まれる oauth コンテンツの受信と処理を行います。 Request_tokenリクエストでoauth_tokenが与えられると、アプリはそれを保存する必要がありません。 Oauth.Managerは賢いので、自動的にそうしてくれます。 同様に、access_tokenリクエストでアクセストークンとシークレットが返ってきたとき、それらを明示的に保存する必要はありません。OAuth.Managerはあなたに代わってその状態を処理します。
その後の実行で、アクセストークンとシークレットをすでに持っている場合は、このようにOAuth.Managerをインスタンス化することができます。
var oauth = new OAuth.Manager();
oauth["consumer_key"] = CONSUMER_KEY;
oauth["consumer_secret"] = CONSUMER_SECRET;
oauth["token"] = your_stored_access_token;
oauth["token_secret"] = your_stored_access_secret;
...そして、上記のように認可ヘッダを生成します。
// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
MessageBox.Show("There's been a problem trying to tweet:" +
Environment.NewLine +
response.StatusDescription);
}
ダウンロードできるのは OAuth.Manager クラスを含む DLL はこちらからダウンロードできます。 . また、ヘルプファイルもダウンロードできます。 また、以下の方法もあります。 オンラインヘルプを見る .
このマネージャを使用したWindowsフォームの例を参照してください。 ここで .
動作例
動作例のダウンロード をダウンロードしてください。
関連
-
[解決済み】MetadataException: 指定されたメタデータ・リソースをロードできない
-
[解決済み】XAMLにSystem.Stringを埋め込む
-
[解決済み] .NETでのdecimal, float, doubleの違い?
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] OpenIDとOAuthの違いは何ですか?
-
[解決済み] AssemblyVersion、AssemblyFileVersion、AssemblyInformationalVersionの違いは何ですか?
-
[解決済み】OAuth v2には、なぜアクセス・トークンとリフレッシュ・トークンの両方があるのでしょうか?
-
[解決済み】.NETにゾンビは存在するのか......?
-
[解決済み】Facebook OAuth "このURLのドメインは、アプリのドメインに含まれていません。"
-
[解決済み] SSOはCASかOAuthか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】コンパイラーエラーメッセージ。コンパイラはエラーコード -532462766 で失敗しました。
-
[解決済み] CLSID {XXXX} を持つコンポーネントの COM クラスファクトリの取得は、次のエラーにより失敗しました: 80040154。
-
[解決済み] BasicHttpsBindingとWsHttpBinding with Transport securityの違いは何ですか?
-
[解決済み] NetFx45WebLinkとNetFx45RedistLinkの違いは何ですか?
-
[解決済み] asp.netでWebサービスのタイムアウト時間を長くする方法は?
-
[解決済み] 24:00:00 を超える値を持つ .Net Timespan を格納するための正しい SQL タイプは何ですか?
-
[解決済み] 権限 '*' を持つ SSL/TLS の安全なチャネルを確立できませんでした。
-
[解決済み] 列挙型を文字列に変換する
-
[解決済み] .Any() vs .Count() > 0のどちらのメソッドがより良いパフォーマンスを発揮しますか?
-
[解決済み] Math.Round(2.5)はなぜ3でなく2を返すのですか?