GoogleのOAuthを試してみた (Java編)

GoogleのOAuthを試してみた でRubyを使ってGoogleのOAuth認証サービスにアクセスできたので、調子に乗ってJava版も作ってみようと思ったのですが、予想以上に大変でした。

忘れないウチにポイントをメモしておきます。

デバッグ用の出力をする設定

oauth - Project Hosting on Google Code にあったJavaのOAuthライブラリを使用しました。このライブラリはHTTP通信にApacheのHttpComponentsを使っています。このライブラリはHTTP通信の内容をログ出力しているので、Log4Jの設定ファイルを書いてログレベルをDEBUGにしておくと、裏で行われているHTTP通信の内容を確認することができます。

これがないとエラーが起こった時に原因が分からないまま試行錯誤を繰り返すことになり、何度やっても上手くいかないのでプログラムを書くのが嫌になって、やがては生きていくのが辛くなるので気をつけないといけません。

 

commons-logging.properties

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

 

log4j.properties

 

log4j.rootLogger=DEBUG, stdout

# Console appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d(%C{1}:%M) %m%n

 

全然関係ないですが、Javaのプロパティファイルの拡張子「.properties」は長すぎると思います。

 

特別なcallback URL「oob」

「oatuth_callback」パラメータを省略するとエラーになります。callback URLを指定したくないときは「oob」という文字列を代わりに指定しないといけません。Rubyで作ったときに使ったライブラリはcallback URLを省略しても上手くいったので気がつくのに時間がかかりました。

 

できあがったソース

さきに使い方から

 

App.java

package syttru.oauth;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

/**
 * Hello world!
 * 
 */
public class App {
  public static void main(String[] args) {
    new App().execute();
  }

  public void execute() {
    
    String consumerKey = "**********";
    String consumerSecret = "************************";
    
    try {
      // コンシューマを生成
      GoogleOauthConsumer consumer = new GoogleOauthConsumer(
          consumerKey, consumerSecret, "oob");
      
      // リクエストトークンを取得するのに使うパラメータ
      Map<String, String> params = new HashMap<String, String>(); 
      params.put("scope", "https://www.google.com/analytics/feeds/");
      // リクエストトークンを取得
      Map<String, String> result = consumer.getRequestToken(params);
      
      // ユーザ認証のURLを作成
      String authURL = consumer.authorizeURL + "?oauth_token="
          + result.get("requestToken");
      System.out.println("以下のURLをWebブラウザで開いてください。");
      System.out.println(authURL);

      // ユーザ認証済みのリクエストトークンを取得
      System.out.print("verifierを入力してね:");
      String verifier = readLineFromStdin();
      result = consumer.getAccessToken(result.get("requestToken"), result
          .get("tokenSecret"), verifier);

      // Google Analyticsのデータを取得
      String response = consumer.getResource(
          "https://www.google.com/analytics/feeds/accounts/default",
          result.get("accessToken"), result.get("tokenSecret"));

      System.out.println(response);

    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * 標準入力から一行取得して返す。
   * 
   * @return 入力された文字列
   */
  public String readLineFromStdin() {
    String line = null;
    try {
      BufferedReader stdReader = new BufferedReader(
          new InputStreamReader(System.in));
      line = stdReader.readLine(); // ユーザの一行入力を待つ
      line = StringUtils.chomp(line);
      stdReader.close();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    return line;
  }
}

 長いー!

 

GoogleOauthConsumer.java

package syttru.oauth;

import static net.oauth.ParameterStyle.*;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

import net.oauth.OAuth;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthException;
import net.oauth.OAuthMessage;
import net.oauth.OAuthServiceProvider;
import net.oauth.client.OAuthClient;
import net.oauth.client.httpclient4.HttpClient4;

/**
 * Google OAuth コンシューマ。
 * 
 * @author makoto
 */
public class GoogleOauthConsumer {

  /** oauth request token URL. */
  public String requestTokenURL =
    "https://www.google.com/accounts/OAuthGetRequestToken";
  /** oauth authorize URL. */
  public String authorizeURL =
    "https://www.google.com/accounts/OAuthAuthorizeToken";
  /** oauth access Token URL. */
  public String accessTokenURL =
    "https://www.google.com/accounts/OAuthGetAccessToken";

  /** oauth consumer key. */
  private String consumerKey;
  /** oauth consumer secret. HMAC-SHA1で署名する時に使う */
  private String consumerSecret;
  /** callback url. ユーザーがGoogleで認証した後にリダイレクトするURL */
  private String callbackURL;

  /**
   * コンストラクタ。
   * 
   * @param consumerKey
   * @param consumerSecret
   * @param callbackURL
   */
  public GoogleOauthConsumer(String consumerKey, String consumerSecret,
      String callbackURL) {
    this.consumerKey = consumerKey;
    this.consumerSecret = consumerSecret;
    this.callbackURL = callbackURL;
  }

  /**
   * Google OAuthのサービスプロバイダを作成する。
   * 
   * @return Google OAuth Service Provider
   */
  public OAuthServiceProvider createGoogleOAuthProvider() {
    return new OAuthServiceProvider(requestTokenURL, authorizeURL,
        accessTokenURL);
  }

  /**
   * Google OAuth用のコンシューマを作成する。
   * 
   * @return Google OAuth Consumer
   */
  public OAuthConsumer createConsumer() {
    OAuthConsumer consumer = new OAuthConsumer(callbackURL, consumerKey,
        consumerSecret, createGoogleOAuthProvider());
    consumer.setProperty("parameterStyle", AUTHORIZATION_HEADER);
    return consumer;
  }

  /**
   * Accessorとやらを作成する。
   * 
   * @return OAuth Accessor
   */
  public OAuthAccessor createAccessor() {
    return new OAuthAccessor(createConsumer());
  }

  /**
   * OAuth用のHTTPクライアントを作成する。
   * 
   * @return HTTPクライアント
   */
  public OAuthClient createClient() {
    return new OAuthClient(new HttpClient4());
  }

  /**
   * リクエストトークンを取得する。
   * 
   * @return requestTokenとtokenSecretが格納されたMap
   * @throws IOException
   * @throws OAuthException
   * @throws URISyntaxException
   */
  public Map<String, String> getRequestToken()
      throws IOException, OAuthException, URISyntaxException {
    return getRequestToken(null);
  }
  /**
   * リクエストトークンを取得する。
   * 
   * @return requestTokenとtokenSecretが格納されたMap
   * @throws IOException
   * @throws OAuthException
   * @throws URISyntaxException
   */
  public Map<String, String> getRequestToken(Map<String, String> params)
      throws IOException, OAuthException, URISyntaxException {
    OAuthClient client = createClient();
    OAuthAccessor accessor = createAccessor();

    Map<String, String> parameters = new HashMap<String, String>();
    parameters.put(OAuth.OAUTH_CALLBACK, accessor.consumer.callbackURL);
    if(params != null) {
      parameters.putAll(params);
    }

    client.getRequestToken(accessor, "GET", parameters.entrySet());

    Map<String, String> ret = new HashMap<String, String>();
    ret.put("requestToken", accessor.requestToken);
    ret.put("tokenSecret", accessor.tokenSecret);

    return ret;
  }

  /**
   * アクセストークンを取得する。
   * 
   * @param requestToken
   * @param tokenSecret
   * @param verifier
   *            ユーザーとサービスプロバイダ間の認証が済んだことを示すもの
   * @return accessTokenとtokenSecretが格納されたMap
   * @throws IOException
   * @throws OAuthException
   * @throws URISyntaxException
   */
  public Map<String, String> getAccessToken(String requestToken, String tokenSecret,
      String verifier) throws IOException, OAuthException,
      URISyntaxException {
    Map<String, String> parameters = new HashMap<String, String>();
    parameters.put("oauth_token", requestToken);
    parameters.put("oauth_verifier", verifier);

    OAuthClient client = createClient();
    OAuthAccessor accessor = createAccessor();
    accessor.tokenSecret = tokenSecret;

    OAuthMessage response =
      client.getAccessToken(accessor, "GET", parameters.entrySet());

    Map<String, String> ret = new HashMap<String, String>();
    ret.put("accessToken", response.getParameter("oauth_token"));
    ret.put("tokenSecret", response.getParameter("oauth_token_secret"));

    return ret;
  }

  /**
   * OAuth認証サービスにアクセスする。
   * 
   * @param url
   * @param accessToken
   * @param tokenSecret
   * @return
   * @throws IOException
   * @throws OAuthException
   * @throws URISyntaxException
   */
  public String getResource(String url, String accessToken, String tokenSecret)
      throws IOException, OAuthException, URISyntaxException {
    Map<String, String> parameters = new HashMap<String, String>();
    parameters.put("oauth_token", accessToken);

    OAuthClient client = createClient();
    OAuthAccessor accessor = createAccessor();
    accessor.tokenSecret = tokenSecret;

    OAuthMessage response = client.invoke(accessor, url, parameters
        .entrySet());

    return response.readBodyAsString();
  }
}

 

うわあああああああああああああああ!!

 

思ったこと

Javaで書くと長くなる。

Trackback URL for this post:

http://blog.smartnetwork.co.jp/staff/trackback/53
from 元、失業SEの開発日誌 on 日, 2011/04/17 - 13:41
参考にさせていただきました。
from ゲリラ的餡子ページ on 土, 2010/05/08 - 05:16
Twitterの普及とともに、サード・パーティのウェブサイトやアプリケーションから、Twitterに...

プロペシア 輸入

プロペシアは、医師に相談してください服用する前にあなたはデュタステリド(Avodart)と呼ばれるような薬、または、この薬にアレルギー反応があった場合。がある場合も医師に相談してください: プロペシア 輸入

ライブラリがどこ??

石田さんのブログを見ると関心しました。 私は今GoogleのAPIについていろいろ調べています。 大変参考にさせていただきました。 必要なライブラリの場所を教えていただきたいんですが、 お時間がよろしいとき、ご返信のほどよろしくお願いします^^。