2012年5月16日水曜日

Facebook に接続

今回は Spring Social です。Spring Social のリファレンス“2. Service Provider 'Connect' Framework”には以下のように記されています。
spring-social-core モジュールは、Facebook や Twitter のような SaaS プロバイダーへの接続を管理するサービスプロバイダー‘コネクションフレームワーク’を含む。このフレームワークは、アプリケーションがローカルユーザーアカウントとユーザーが外部のサービスプロバイダーに持っているアカウント間のコネクションを確立することを可能とする
前回までに、アカウント管理の基本的な仕掛けはできたので、これをベースに Facebook に接続したいと思います。

準備
Spring Social から以下のパッケージをダウンロードし、解凍後、/WEB-INF/lib とビルドパスに登録します。

spring-social-1.0.2.RELEASE.zip
spring-social-facebook-1.0.1.RELEASE.zip

また、リファレンス“1.4 Dependencies”を参考に足りないコンポーネントを追加します。私の場合、以下のものを追加しました。

Jackson JSON Processor
jackson-all-1.9.7.jar

App ID の取得
Facebook for Websitesに行き、“Authentication”に記された要領に従いウェブサイトの App ID(と App Secret)を取得します。その際、アプリの「表示名」や「ドメイン」の他、OAuth2 認証時のリダイレクト(コールバック)先となる「サイト URL」を予め決めておく必要があります。

因みに私の場合、localhost で開発しているので図のような感じになります。

権限とポートのマッピング
前回、アプリケーションにアカウントを作成したユーザーに ROLE_USER という権限を割当てる仕掛けを作りこみました。今回の目的は、そうしたアプリ内のローカルユーザーと Facebook アカウントを(access token で)結びつけることです。言い換えれば、ROLE_USER という権限を付与された認証済みのローカルユーザーだけにアプリケーション(facebooktest)の使用を許可するということです。この要件を踏まえて、springSecurityConf.xml の <security:http/> 要素内に以下の行を追加しました。接続は https です。
  <security:http auto-config="true">
    :
    <!-- social service -->
    <security:intercept-url pattern="/facebooktest/**" requires-channel="https" access="ROLE_USER"/>
    :
  </security:http>



facebook に接続 - 直球型
リファレンス“2.2.1 OAuth2 service providers”に OAuth2 のフローが記されています。その下にあるのが Facebook に接続するコード例です。これに倣い、アプリケーションの認証からアクセストークンを受け取るまでのコードを作ってみます。

まずは、Facebook にアプリケーションの認証要求を送信する部分。フローは以下の通りです。
  1. FacebookConnectionFactory のコンストラクター引数に Facebook から発行された App Id と App Secret をセットしてインスタンス化し
  2. それから OAuth2 フローを制御するサービスインターフェース OAuth2Operationsを取得します。
  3. OAuth2Parameters オブジェクトに Facebook に登録したサイト URL(コールバックURL)をセットし
  4. OAuth2Operations の buildAuthorizeUrl() メソッドで Facebook にアプリケーションを認証してもらうための URL を生成します。
  5. 生成した URL にリダイレクトします。

以下が実際のコードです。facebooktest/signin.html を呼び出すと Facebook との“OAuth2 ダンス”が始まります。callbackUrl は、コールバック URL です。
@Controller
public class FacebookTestController {

  private OAuth2Operations oauthOperations;
    :
  @RequestMapping(value = "facebooktest/signin.html", method = RequestMethod.GET)
  public void signin(HttpServletResponse response) 
    throws IOException {
    FacebookConnectionFactory connectionFactory = new FacebookConnectionFactory("[App Id]", "[App Secret]");
    oauthOperations = connectionFactory.getOAuthOperations();
    OAuth2Parameters params = new OAuth2Parameters();
    params.setRedirectUri(callbackUrl);
    String authorizeUrl = oauthOperations.buildAuthorizeUrl(GrantType.AUTHORIZATION_CODE, params);
    logger.info("auth url: {}", authorizeUrl);
    response.sendRedirect(authorizeUrl);
  }
}

生成した authorizeUrl の内容はこんな感じです。

https://graph.facebook.com/oauth/authorize?client_id=[App Id]&response_type=code&redirect_uri=https%3A%2F%2Flocalhost%3A8443%2Fishtar%2Ffacebooktest%2Fhello.html

Facebook にログインしていない状態で facebooktest/signin.html にアクセスすると下図の画面が現れます。


Facebook にログインするとコールバック URLにリダイレクトされてきます。それを受け止めるのが以下のコードです。
  @RequestMapping(value = "facebooktest/hello.html", method = RequestMethod.GET)
  public ModelAndView hello(@RequestParam(value = "code", required = true) String code) {
    
    ModelAndView mav = new ModelAndView();
    
    if (code == null) {
      mav.setViewName("redirect:signin.html");
      return mav;
    }
    
    AccessGrant accessGrant = oauthOperations.exchangeForAccess(code, callbackUrl, null);
    Connection<Facebook> connection = facebookConnectionFactory.createConnection(accessGrant);
    logger.info(">>access token: {}", accessGrant.getAccessToken());
    
    Facebook fb = connection.getApi();
    FacebookProfile fbProfile = fb.userOperations().getUserProfile();
    mav.addObject("fbProfile", fbProfile);
    mav.setViewName("home/index");
    
    return mav;
  }
  1. まず、リクエストパラメーターにFacebookからの認証コード“code”が含まれていなかったら前述の signin.html にリダイレクトします。
  2. OAuth2Operations の exchangeForAccess()メソッドで Facebook から受け取った認証コードを送り返し、AccessGrantを受け取ります。
  3. 受け取った AccessGrant に含まれている Access Token を使って Connection オブジェクトを生成します。
  4. Facebook インターフェースの userOperations()メソッドを介して Facebook に登録しているプロフィールを取得し、ModelAndView にセットして View を呼び出しています。

以上で、Facebook に接続するという目的は達成です。

0 件のコメント:

コメントを投稿