mixi Developer Center (ミクシィ デベロッパーセンター)

mixiアプリ

mixiアプリ » mixiアプリ for PC » mixiアプリを作ってみよう » 外部サーバを呼び出してみよう

外部サーバを呼び出してみよう

mixiアプリは、Person & Friends APIを利用することによって、ソーシャルという特徴を持つことになります。それに加えて、インターネット上にある無数のWebサービス(外部サーバ)が提供するコンテンツとのマッシュアップによって、mixiアプリの魅力は何倍にも大きなものとなります。すでに海外などで人気を得ている OpenSocialアプリケーションのほとんどが、任意のWebサービスを呼び出してコンテンツを利用しています。単に外部のコンテンツを表示するだけでなく、ソーシャルグラフと関連付けることによって、新しいユーザ体験を提供することができます。

makerequest1

mixiアプリから外部サーバへ通信を行うための機構は、OpenSocial仕様においてGadgets Core JavaScript APIとして定義されています。具体的に外部サーバへ通信を行うための関数は、gadgets.io.makeReqeust()関数です。mixiアプリは、このmakeRequest()関数を利用することで、外部サーバからコンテンツを取得することができます。

makeRequest()関数の主要な機能

makeRequest()関数は非常に強力な機能をいくつか提供しますが、その使用方法は比較的シンプルです。この関数は、以下のような特徴を持っています。

  • HTTP Methodとして、GETやPOSTなど、ほとんどのMethodをサポートしている
  • 外部サーバから返却されるコンテンツについて、主要ないくつかの形式がサポートされており、JavaScriptにおいて扱いやすい形式に変換される
  • 署名などセキュリティに関する仕様が取り入れられているため、安全に外部サーバと通信することができる

makeRequest()関数を使用する際、以下の引数を指定します。

  • 取得したいコンテンツの位置を示すURL
  • 結果が返却された際に呼び出されるコールバック関数
  • 外部サーバへの要求に関するパラメータ

指定可能なパラメータは、gadgets.io.RequestParametersクラスに定義されています。これらのパラメータをうまく使うことで、外部サーバへの要求をカスタマイズすることが可能です。

gadgets.io.AUTHORIZATION

makeRequest()関数による外部サーバへのアクセスについて、署名を付与することができます。署名つきとするかどうかは、AUTHORIZATIONパラメータで指定します。

  • gadgets.io.AuthorizationType.NONE – 署名を付与しない
  • gadgets.io.AuthorizationType.SIGNED – 署名を付与する

※ mixiアプリから外部サーバへのOAuthによる認証認可要求は、現在サポートされていません。

gadgets.io.CONTENT_TYPE

CONTENT_TYPEパラメータにより、外部サーバから得られるコンテンツの期待する形式を指定することができます。この指定によって、コンテンツはJavaScriptオブジェクトに自動的に変換され、mixiアプリから扱いやすくなります。

  • gadgets.io.ContentType.DOM – XML形式の結果を期待する
  • gadgets.io.ContentType.FEED – RSSまたはATOM Feed形式の結果を期待する
  • gadgets.io.ContentType.JSON – JSON文字列形式の結果を期待する
  • gadgets.io.ContentType.TEXT – テキストそのままの形式の結果を期待する

そのほかにも、METHODパラメータによるHTTP Methodの指定や、POST_DATAパラメータによるPOST時に送信する情報の指定を行うことができます。

makeRequest()関数の第2引数で指定するコールバック関数には、結果を持つオブジェクトが呼び出し時に渡されます。そのオブジェクトは、以下のプロパティを持ちます。

  • data – 要求の際に指定したコンテンツの種別に応じて適切に変換された結果が保持される
  • rc – 要求の結果のHTTPステータスコードが保持される
  • errors – 要求の結果として何らかのエラーが返された際に、エラー情報が配列として保持される
  • text – 要求の結果として得られたコンテンツの文字列が保持される

これらのプロパティから、外部サーバから得られたコンテンツを利用することができます。

サンプルコード

以下のリストは、外部サーバからフィード文書を取得し、その結果を処理する例です。

var url = "http://your.server.host/recent";
var params = {};
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.FEED;
var post_data = {span : 7};
params[gadgets.io.RequestParameters.POST_DATA] = gadgets.io.encodeValues(post_data);
params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.NONE;
gadgets.io.makeRequest(url, function(response) {
  var feed = response.data;
  var title = feed.Title;
  var link = feed.Link;
  // do something...
  var entries = feed.Entry;
  for (var i = 0; i < entries.length; i++) {
    var entry = entries[i];
    var entryTitle = entry.Title;
    var entryLink = entry.Link;
    // do something...
  }
}, params);

アクセス制限

mixi Platformの全体的な負荷対策として、mixiアプリ(PC版)から外部サーバに通信を行うためにご提供しているgadgets.io.makeRequest()関数について、以下の制限を実施いたします。

  • 接続先ホストへの通信が20回連続でタイムアウト(10秒)した場合、そのホストへの通信は15秒間行うことができない。
  • 15秒間の制限時間内にmakeRequest()にて通信を試みた場合には、エラーコード504を含むレスポンスが返されます(通常タイムアウトした場合と同じです)。

上記の各数値は、今後mixi Platformの稼働状況に応じて予告なく変更する可能性がございますので、ご了承ください。

署名付きリクエスト

makeRequest()関数を使ってmixiアプリは外部サーバと通信が行えるようになりますが、そのリクエストを受け付ける外部サーバ側では、そのリクエストの妥当性を確認することが必要となる場合が考えられます。具体的には、

  • mixi Platformから送信されたリクエストであること
  • リクエストの内容が改ざんされていないこと

をチェックすることにより、これらに違反する不正なリクエストを拒否することが可能となります。

署名付きリクエストを行うためには、AUTHORIZATIONパラメータにSIGNEDを指定します。以下のリストは、署名付きリクエストを行う処理の例です。

var url = "http://your.server.host/recent";
var params = {};
params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
gadgets.io.makeRequest(url, function(response) {
  // do something...
}, params);

書名付きリクエストの際に外部サーバに対して送信されるリクエストについて、mixiアプリでは以下のパラメータ値となります。

  • oauth_consumer_key – “mixi.jp”
  • oauth_signature_method – “RSA-SHA1″

リクエストの内容は、各パラメータの値、oauth_signatureパラメータ値として付与された署名、そして公開鍵を使って、リクエストの妥当性を検証することができます。

公開鍵

-----BEGIN CERTIFICATE-----
MIICdzCCAeCgAwIBAgIJANCWpLIspxwbMA0GCSqGSIb3DQEBBQUAMDIxCzAJBgNV
BAYTAkpQMREwDwYDVQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDAeFw0x
MDAzMjMwODE1NTlaFw0xMjAzMjIwODE1NTlaMDIxCzAJBgNVBAYTAkpQMREwDwYD
VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDCBnzANBgkqhkiG9w0BAQEF
AAOBjQAwgYkCgYEAtbq5Rns5IEktXldZ+37Fjlavnuc4JuwrD4F+4NQwVwVtR5yw
Vg10EanXWSGIAbUFx6hlppYOb0x/3PBMG80643LmXSJmvv4ViRUBl2Ys9Ie2L/D9
KVQXDWgJjxBGqo5MO6rA/Ip78kbiNbIQJUIJtbuJZWL3LMVe6mpIO2SUi1UCAwEA
AaOBlDCBkTAdBgNVHQ4EFgQU8bp8/6lmt5L8em6dZyoGciUUmuUwYgYDVR0jBFsw
WYAU8bp8/6lmt5L8em6dZyoGciUUmuWhNqQ0MDIxCzAJBgNVBAYTAkpQMREwDwYD
VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcIIJANCWpLIspxwbMAwGA1Ud
EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEApalbBgXxnLJW8fM6W7E7GAE4QZbE
lvYqvtQSxwacGYoqF2FW1zrBkmTB12LTddFU01pqDaeels3Ru5TNOnTIJemFWW0D
viKtu9GqsrOye6AZR+XA5Iy/vq3EV1TCGuDNmhJaHAiLeYuLbEqmvH7/l9xNsafH
IpqnsHwF1pm0bTY=
-----END CERTIFICATE-----

署名付きリクエストの検証

この記事では、署名付きリクエストをどのように検証するかを説明します。もしあなたが署名付きリクエストとは何かわからない場合や、なぜこれを使わなければならないのかわからない場合は、署名付きリクエストの紹介ページをチェックしてください。

※ ここより先の内容は、「Validating Signed Requests」の翻訳に一部修正を加えたものです。

http://wiki.opensocial.org/index.php?title=Validating_Signed_Requests

暗号化キーを入手する

署名付きリクエストは、現在3つのパラメータを含みます。

  • oauth_consumer_key
  • xoauth_signature_publickey
  • oauth_signature_method

oauth_consumer_keyパラメータは、リクエストが送信されたコンテナを示します。oauth_signature_methodパラメータは、リクエストを署名するために使われたメソッドを示します。RSA-SHA1で署名されたリクエストのために、 xoauth_signature_publickeyはリクエストを署名するために使われた公開鍵の名前を含みます。

HMAC-SHA1のために、あなたはあなたのアプリケーションとコンテナの間でSecret keyを確立する必要があるでしょう。各コンテナは、それをするために異なるメカニズムを持ちますので、共有Secret keyを確立することに関する情報を得るために、あなたが対象とするコンテナのドキュメントを参照してください。

RSA-SHA1のために、あなたはxoauth_signature_publickeyによって参照される証明書を入手する必要があるでしょう。あなたの利便性のために、各証明書へのリンクを含む各コンテナで利用可能な公開鍵の一覧が https://opensocialresources.appspot.com/certificates/ にあります。このサイトは、利便性のためのみのものであり、各コンテナによって承認されたリストではありません!ベストなセキュリティにおいて、承認された公開鍵の位置を検証するために、必ずあなたのコンテナのドキュメントをチェックしてください!

証明書は、あなたがパラメータを検証したい度に取得されるべきではありません。その代わりに、 xoauth_signature_publickey、oauth_consumer_key、そしてoauth_signature_methodの値でインデックスされた、サーバサイドの鍵キャッシュ機構を実装してください。もしそれらの値に変更があった際には、あなたはあなたの鍵キャッシュの中で、新しい証明書をダウンロードし格納する必要があるでしょう。

OAuth署名メカニズム

パラメータの署名は、OAuthパラメータ署名仕様に従って実装されます。

署名ベース文字列を生成することに関する情報は、このページをチェックしてください。

http://oauth.net/core/1.0/#rfc.section.A.5.1

PHP

クライアントサイドコード

あなたのクライアントコードは、以下の作法においてリクエストを作るべきです。私たちは、gadgets.io.AuthorizationType.SIGNEDリクエストを指定し、そしてJSONとして返される結果を期待するでしょう。

function makeSignedRequest() {
  var params = {};
  params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
  var url = "http://graargh.returnstrue.com/buh/fetchme.php";
  gadgets.io.makeRequest(url, response, params);
};

function response(ret) {
  output(ret.data);

  var html = [ ret.data.validated, "<br />",
    "oauth_consumer_key: ", ret.data.query.oauth_consumer_key, "<br />",
    "oauth_nonce: ", ret.data.query.oauth_nonce, "<br />",
    "oauth_signature: ", ret.data.query.oauth_signature, "<br />",
    "oauth_signature_method: ", ret.data.query.oauth_signature_method, "<br />",
    "oauth_timestamp: ", ret.data.query.oauth_timestamp, "<br />",
    "oauth_token: ", ret.data.query.oauth_token, "<br />",
    "opensocial_app_id: ", ret.data.query.opensocial_app_id, "<br />",
    "opensocial_owner_id: ", ret.data.query.opensocial_owner_id, "<br />",
    "xoauth_signature_publickey: ", ret.data.query.xoauth_signature_publickey
].join("");

  output(html);
};

makeSignedRequest();

サーバサイドコード

以下のコードは、fetchme.phpというサーバサイドコードとなります。このコードは、オープンソースのOAuthライブラリプロジェクトにあるOAuth.php (リビジョン 526)に依存しています。

http://code.google.com/p/oauth/
http://oauth.googlecode.com/svn-history/r526/code/php/OAuth.php

コードは、以下の手順で実装されています:

  • OAuthSignatureMethod_RSA_SHA1を継承したMixiSignatureMethodクラスを作成。
  • 受け取ったリクエストからOAuthRequestオブジェクトを生成。
  • MixiSignatureMethodのインスタンスを生成。
  • MixiSignatureMethodクラスを使ってリクエストをチェック。
  • JSONオブジェクトを出力。

この例は、プロダクション品質のコードではありません。ただ単に、あなたがサーバサイドで署名付きリクエストを検証することを試すための手順のデモに過ぎません。

require_once("OAuth.php");

class MixiSignatureMethod extends OAuthSignatureMethod_RSA_SHA1 {
  protected function fetch_public_cert(&$request) {
  return <<< EOD
-----BEGIN CERTIFICATE-----
MIICdzCCAeCgAwIBAgIJANCWpLIspxwbMA0GCSqGSIb3DQEBBQUAMDIxCzAJBgNV
BAYTAkpQMREwDwYDVQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDAeFw0x
MDAzMjMwODE1NTlaFw0xMjAzMjIwODE1NTlaMDIxCzAJBgNVBAYTAkpQMREwDwYD
VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDCBnzANBgkqhkiG9w0BAQEF
AAOBjQAwgYkCgYEAtbq5Rns5IEktXldZ+37Fjlavnuc4JuwrD4F+4NQwVwVtR5yw
Vg10EanXWSGIAbUFx6hlppYOb0x/3PBMG80643LmXSJmvv4ViRUBl2Ys9Ie2L/D9
KVQXDWgJjxBGqo5MO6rA/Ip78kbiNbIQJUIJtbuJZWL3LMVe6mpIO2SUi1UCAwEA
AaOBlDCBkTAdBgNVHQ4EFgQU8bp8/6lmt5L8em6dZyoGciUUmuUwYgYDVR0jBFsw
WYAU8bp8/6lmt5L8em6dZyoGciUUmuWhNqQ0MDIxCzAJBgNVBAYTAkpQMREwDwYD
VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcIIJANCWpLIspxwbMAwGA1Ud
EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEApalbBgXxnLJW8fM6W7E7GAE4QZbE
lvYqvtQSxwacGYoqF2FW1zrBkmTB12LTddFU01pqDaeels3Ru5TNOnTIJemFWW0D
viKtu9GqsrOye6AZR+XA5Iy/vq3EV1TCGuDNmhJaHAiLeYuLbEqmvH7/l9xNsafH
IpqnsHwF1pm0bTY=
-----END CERTIFICATE-----
EOD;
  }
}

//Build a request object from the current request
$request = OAuthRequest::from_request(null, null, array_merge($_GET, $_POST));

//Initialize the new signature method
$signature_method = new MixiSignatureMethod();

//Check the request signature
@$signature_valid = $signature_method->check_signature($request, null, null, $_GET["oauth_signature"]);

//Build the output object
$payload = array();
if ($signature_valid == true) {
  $payload["validated"] = "Success! The data was validated";
} else {
  $payload["validated"] = "This request was spoofed";
}

//Add extra parameters to help debugging
$payload["query"] = array_merge($_GET, $_POST);
$payload["rawpost"] = file_get_contents("php://input");

//Return the response as JSON
print(json_encode($payload));

結果

あなたがサーバコードに対してクライアントサイドのスクリプトを実行したとき、”response”関数は以下のオブジェクトのひとつを伴って呼び出されるでしょう:

もしリクエストが検証された場合:

{ "validated" : "Success! The data was validated",
  "query" : {  }
}

もしリクエストが検証されなかった場合:

{ "validated" : "This request was spoofed",
  "query" : {  }
}

この結果は以下の書式で出力されます:

Success! The data was validated
oauth_consumer_key: mixi.jp
oauth_nonce: c970afeb19325be3
oauth_signature: #### REALLY LONG STRING ###
oauth_signature_method: RSA-SHA1
oauth_timestamp: 1201225242
oauth_token:
opensocial_appid: ############
opensocial_ownerid: ############
xoauth_signature_publickey: pub.1199819524.-1556113204990931254.cer

Java

クライアントサイドコード

var servletUrl="http://oauthtest.s42.eatj.com/oauth/SignedFetchVerifyServlet";
function response(data) {
  document.getElementById('dom_handle').innerHTML=data.text;
};
function request() {
  var params={};
  params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
  gadgets.io.makeRequest(servletUrl,response,params);
};
gadgets.util.registerOnLoadHandler(request);

サーバサイドコード

コードは以下の手順で実装されます:

  • OAuthServiceProviderを生成します。
  • OAuthConsumerを生成し、mixiの証明書を伴うRSA証明書を投入します。
  • HttpServletRequestからOAuthMessageを展開します。
  • consumerを使ってOAuthAccessorを生成します。
  • accessorを使ってOAuthMessageを検証します。

このコードは、オープンソースのOAuthライブラリプロジェクトのJava実装に依存します。

http://code.google.com/p/oauth/

この例は、プロダクション品質のコードではありません。ただ単に、あなたがサーバサイドで署名付きリクエストを検証することを試すための手順のデモに過ぎません。

package net.oauth.example.provider.servlets;

import net.oauth.OAuth;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthMessage;
import net.oauth.OAuthProblemException;
import net.oauth.OAuthServiceProvider;
import net.oauth.OAuthValidator;
import net.oauth.SimpleOAuthValidator;
import net.oauth.server.OAuthServlet;
import net.oauth.signature.RSA_SHA1;

import java.util.ArrayList;
import java.io.IOException;
import java.util.Map;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SignedFetchVerifyServlet extends HttpServlet {

  private final static String CERTIFICATE =
    "-----BEGIN CERTIFICATE-----\n"
    + "MIICdzCCAeCgAwIBAgIJANCWpLIspxwbMA0GCSqGSIb3DQEBBQUAMDIxCzAJBgNV\n"
    + "BAYTAkpQMREwDwYDVQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDAeFw0x\n"
    + "MDAzMjMwODE1NTlaFw0xMjAzMjIwODE1NTlaMDIxCzAJBgNVBAYTAkpQMREwDwYD\n"
    + "VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDCBnzANBgkqhkiG9w0BAQEF\n"
    + "AAOBjQAwgYkCgYEAtbq5Rns5IEktXldZ+37Fjlavnuc4JuwrD4F+4NQwVwVtR5yw\n"
    + "Vg10EanXWSGIAbUFx6hlppYOb0x/3PBMG80643LmXSJmvv4ViRUBl2Ys9Ie2L/D9\n"
    + "KVQXDWgJjxBGqo5MO6rA/Ip78kbiNbIQJUIJtbuJZWL3LMVe6mpIO2SUi1UCAwEA\n"
    + "AaOBlDCBkTAdBgNVHQ4EFgQU8bp8/6lmt5L8em6dZyoGciUUmuUwYgYDVR0jBFsw\n"
    + "WYAU8bp8/6lmt5L8em6dZyoGciUUmuWhNqQ0MDIxCzAJBgNVBAYTAkpQMREwDwYD\n"
    + "VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcIIJANCWpLIspxwbMAwGA1Ud\n"
    + "EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEApalbBgXxnLJW8fM6W7E7GAE4QZbE\n "
    + "lvYqvtQSxwacGYoqF2FW1zrBkmTB12LTddFU01pqDaeels3Ru5TNOnTIJemFWW0D\n"
    + "viKtu9GqsrOye6AZR+XA5Iy/vq3EV1TCGuDNmhJaHAiLeYuLbEqmvH7/l9xNsafH\n"
    + "IpqnsHwF1pm0bTY="
    + "-----END CERTIFICATE-----";

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                           throws ServletException, IOException {
    verifyFetch(req, resp);
  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                            throws ServletException, IOException {
    verifyFetch(req, resp);
  }

  private void verifyFetch(HttpServletRequest request, HttpServletResponse resp)
                                    throws IOException, ServletException {
    resp.setContentType("text/html; charset=UTF-8");
    PrintWriter out = resp.getWriter();

    try {
      OAuthServiceProvider provider = new OAuthServiceProvider(null, null, null);
      OAuthConsumer consumer = new OAuthConsumer(null, "mixi.jp", null, provider);
      consumer.setProperty(RSA_SHA1.X509_CERTIFICATE, CERTIFICATE);

      String method = request.getMethod();
      String requestUrl = getRequestUrl(request);
      List requestParameters = getRequestParameters(request);

      OAuthMessage message = new OAuthMessage(method, requestUrl, requestParameters);

      OAuthAccessor accessor = new OAuthAccessor(consumer);
      out.print("*** OAuthMessage Params:");
      out.print("URL: " + OAuthServlet.htmlEncode(message.URL));
      for (java.util.Map.Entry param : message.getParameters()) {
        String key = param.getKey().toString();
        String value = param.getValue().toString();
        out.print("");
        out.print("Param Name-->" + OAuthServlet.htmlEncode(key));
        out.print(" ");
        out.print("Value-->" + OAuthServlet.htmlEncode(value));
      }
      out.print("");
      out.print(" VALIDATING SIGNATURE ");
      out.print("");
      OAuthValidator validator = new SimpleOAuthValidator();
      validator.validateMessage(message, accessor);
      out.print("REQUEST STATUS::OK");
      out.print("");
    } catch (OAuthProblemException ope) {
      out.print("");
      out.print("OAuthProblemException-->" + OAuthServlet.htmlEncode(ope.getProblem()));
    } catch (Exception e) {
      out.println(e);
      System.out.println(e);
      throw new ServletException(e);
    } finally {
      out.flush();
    }
  }

  /**
   * Constructs and returns the full URL associated with the passed request
   * object.
   *
   * @param  request Servlet request object with methods for retrieving the
   *         various components of the request URL
   */
  public static String getRequestUrl(HttpServletRequest request) {
    StringBuilder requestUrl = new StringBuilder();
    String scheme = request.getScheme();
    int port = request.getLocalPort();

    requestUrl.append(scheme);
    requestUrl.append("://");
    requestUrl.append(request.getServerName());

    if ((port != 0) && (
        (scheme.equals("http") && port != 80)
    || (scheme.equals("https") && port != 443))) {
      requestUrl.append(":");
      requestUrl.append(port);
    }

    requestUrl.append(request.getContextPath());
    requestUrl.append(request.getServletPath());

    return requestUrl.toString();
  }

  /**
   * Constructs and returns a List of OAuth.Parameter objects, one per
   * parameter in the passed request.
   *
   * @param  request Servlet request object with methods for retrieving the
   *         full set of parameters passed with the request
   */
  public static List getRequestParameters(HttpServletRequest request) {

    List parameters = new ArrayList();

    for (Object e : request.getParameterMap().entrySet()) {
      Map.Entry entry = (Map.Entry) e;

      String[] values = (String[])entry.getValue();
      for (String value : values) {
        parameters.add(new OAuth.Parameter(entry.getKey(), value));
      }
    }

    return parameters;
  }
}

結果

あなたがサーバコードに対してクライアントサイドのスクリプトを実行したとき、そしてリクエストが検証されたとき:

*** OAuthMessage Params:
URL: http://oauthtest.s42.eatj.com/oauth/SignedFetchVerifyServlet
Param Name-->oauth_consumer_key Value-->mixi.jp
Param Name-->oauth_nonce Value-->7fe2ce6b24e17c86
Param Name-->opensocial_app_id Value-->10449685582340194994
Param Name-->opensocial_viewer_id Value-->10972140642666904206
Param Name-->oauth_timestamp Value-->1211519778
Param Name-->opensocial_owner_id Value-->10972140642666904206
Param Name-->oauth_signature Value-->eYwX2yWLpOZ+gb5oEFeIy+EM3j237nrj/1rj3yp69jgo
/QaPk/OnXbXP9imEcERxtQLj9QqDD8cjbjMJ46VINc7b
Lab8qER1Xhkf4tTIkwfFXJW9tjQMBuGO8OVf9v0UAjAr
uWfSN331LLgGFecKQR5UTD0qAAyzTnFY9aSmqg8=
Param Name-->xoauth_signature_publickey Value-->pub.1199819524.-1556113204990931254.cer
Param Name-->oauth_token Value-->
Param Name-->oauth_signature_method Value-->RSA-SHA1
VALIDATING SIGNATURE
REQUEST STATUS::OK

C#

サーバサイドコード

このコードは、オープンソースのOAuthライブラリプロジェクトのC#向けOAuthライブラリに依存しています。

http://code.google.com/p/oauth/

この例は、プロダクション品質のコードではありません。ただ単に、あなたがサーバサイドで署名付きリクエストを検証することを試すための手順のデモに過ぎません。

// -----------------------------------------------------------------------------------
//
//  OBasePage.cs to validate oAuth signature - .NET
//  by XtremeHeights
//  Last Modification: 4th Oct 2008
//
//  For more information, visit:
//  http:/www.xtremeheights.com/
//  email: contact@xtremeheights.com
//
//
//  Thanks:
//  Khushal Patel for creating plug & plug code for implementing oAuth in .NET
//  Nemesh Singh for fixing the code which started spoofing every request after 25th sep 2008
//
// -----------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Configuration;
using System.Web;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Collections.Specialized;
using OAuth;

public class oBasePage : System.Web.UI.Page
{
  HttpContext htp;
  public oBasePage(HttpContext _htp)
  {
    htp = _htp;
  }

  public bool isvalidrequest()
  {
    //If you want to import certificate file directly then uncomment the below line and comment the certificate
    //X509Certificate Cert = X509Certificate.CreateFromCertFile(htp.Request.PhysicalApplicationPath + "/bin/pub.1199819524.-1556113204990931254.cer");

    X509Certificate2 cert = new X509Certificate2();
    cert.Import(Encoding.ASCII.GetBytes(
@"-----BEGIN CERTIFICATE-----
MIICdzCCAeCgAwIBAgIJANCWpLIspxwbMA0GCSqGSIb3DQEBBQUAMDIxCzAJBgNV
BAYTAkpQMREwDwYDVQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDAeFw0x
MDAzMjMwODE1NTlaFw0xMjAzMjIwODE1NTlaMDIxCzAJBgNVBAYTAkpQMREwDwYD
VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDCBnzANBgkqhkiG9w0BAQEF
AAOBjQAwgYkCgYEAtbq5Rns5IEktXldZ+37Fjlavnuc4JuwrD4F+4NQwVwVtR5yw
Vg10EanXWSGIAbUFx6hlppYOb0x/3PBMG80643LmXSJmvv4ViRUBl2Ys9Ie2L/D9
KVQXDWgJjxBGqo5MO6rA/Ip78kbiNbIQJUIJtbuJZWL3LMVe6mpIO2SUi1UCAwEA
AaOBlDCBkTAdBgNVHQ4EFgQU8bp8/6lmt5L8em6dZyoGciUUmuUwYgYDVR0jBFsw
WYAU8bp8/6lmt5L8em6dZyoGciUUmuWhNqQ0MDIxCzAJBgNVBAYTAkpQMREwDwYD
VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcIIJANCWpLIspxwbMAwGA1Ud
EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEApalbBgXxnLJW8fM6W7E7GAE4QZbE
lvYqvtQSxwacGYoqF2FW1zrBkmTB12LTddFU01pqDaeels3Ru5TNOnTIJemFWW0D
viKtu9GqsrOye6AZR+XA5Iy/vq3EV1TCGuDNmhJaHAiLeYuLbEqmvH7/l9xNsafH
IpqnsHwF1pm0bTY=
-----END CERTIFICATE-----"));

    //Getting Post variables
    string http_params;
    NameValueCollection _p = htp.Request.Form;
    Hashtable _hp = new Hashtable();

    foreach (string k in _p.Keys)
    {
      if (k != null)
      {
        _hp[k] = _p[k];
      }
    }

    SortedList _ps = new SortedList((IDictionary)_hp);

    string[] pairs1 = new string[_ps.Keys.Count];
    int l = 0;

    foreach (string name in _ps.Keys)
    {
      pairs1[l++] = name + "=" + Uri.EscapeDataString(_ps[name].ToString());
    }
    http_params = (String.Join("&", pairs1));

    if (_ps.Keys.Count != 0)
    {
      http_params = "&" + http_params;
    }

    /* RSACryptoServiceProvider Provider = CertUtil.GetCertPublicKey(Cert); // if importing the file directly... */
    RSACryptoServiceProvider Provider = (RSACryptoServiceProvider)cert.PublicKey.Key;
    OAuth.OAuthBase ba = new OAuthBase();

    string signature = (htp.Request.QueryString["oauth_signature"]);

    string baseString = ba.GenerateSignatureBase(htp.Request.Url,
      htp.Request.QueryString["oauth_consumer_key"],
      "",
      htp.Request.QueryString["oauth_token"],
      "",
      htp.Request.HttpMethod,
      htp.Request.QueryString["oauth_timestamp"],
      htp.Request.QueryString["oauth_nonce"],
      "RSA-SHA1",
      http_params);

    byte[] sign = Convert.FromBase64String(signature);
    byte[] bstring = Encoding.UTF8.GetBytes(baseString);
    htp.Response.Write(htp.Request.QueryString["oauth_token"]);

    return (Provider.VerifyData(bstring, "SHA1", sign));
  }
}

もしあなたがこのページに関して何かコメントもしくは質問をお持ちの場合は、OpenSocial Developerフォーラムにてディスカッションしてください。

http://groups.google.com/group/opensocial-api/topics

このページの上部へ