LoginSignup
14
11

More than 5 years have passed since last update.

GAE/JからOAuth2.0を使用してSpreadsheetを参照する

Last updated at Posted at 2014-03-15

以下のサイトを参考にGAEからSpreadsheetを参照するプロジェクトを作ってみたのですがOAuth2.0に対応させるのにえらく手こずったのでメモを残しておきます。

使用するのは「GData API」で環境構築の手順は下記の記事と同じです。また、フレームワークは「Slim3+Scenic3」を利用しています。こちらは公式サイトを参考に。

GData APIでGoogleスプレッドシートを参照するには
http://www.atmarkit.co.jp/ait/articles/1001/15/news121.html
Slim3
https://sites.google.com/site/slim3documentja/
Scenic3
https://sites.google.com/site/aboutscenic3/home

作ったものは http://localhost:8888/spreadsheet にアクセスするとspreadsheetの内容を出力する簡単なWEBアプリです。非常に手抜き処理ばかりですし、たいしてテストしていないプログラムですががご参考までに。

TestPage.java
package test.page;

import test.service.CredentialDataService;

import java.net.URL;
import java.util.Arrays;
import java.util.List;

import org.slim3.controller.Navigation;

import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.drive.DriveScopes;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.spreadsheet.ListEntry;
import com.google.gdata.data.spreadsheet.ListFeed;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.WorksheetEntry;

import scenic3.annotation.ActionPath;
import scenic3.annotation.Page;

@Page("/")
public class TestPage extends CommonPage {

    private static final String CLIENT_ID_DEBUG =
        "<ローカルテスト用クライアントID>";
    private static final String CLIENT_SECRET_DEBUG =
        "<ローカルテスト用クライアントシークレット>";
    private static final String REDIRECT_URI_DEBUG =
        "http://localhost:8888/oauth2callback";

    private static final String CLIENT_ID = "<GAE環境用クライアントID>";
    private static final String CLIENT_SECRET = "<GAE環境用シークレット>";
    private static final String REDIRECT_URI =
        "http://<自分のプロジェクトのドメイン>/oauth2callback";

    private static final List<String> SCOPES = Arrays.asList(
        DriveScopes.DRIVE_FILE,
        "https://spreadsheets.google.com/feeds");

    private static final HttpTransport TRANSPORT = new NetHttpTransport();
    private static final JsonFactory JSON_FACTORY = new JacksonFactory();

    private static final String SERVICE_NAME = "<サービス名>";

    CredentialDataService credentialService = new CredentialDataService();

    /**
     * デバッグ用サーバかどうか
     */
    private boolean isDebug() {
        String serverName = request.getServerName();
        if (serverName.indexOf("localhost") != -1) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 文字列をレスポンスに出力
     */
    private void writeResponse(String str) {
        try {
            response.setCharacterEncoding("utf-8");
            response.getWriter().println(str);
            response.flushBuffer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * OAuth認証用flowインスタンスを取得
     */
    private GoogleAuthorizationCodeFlow getFlow() {

        String clientId, clientSecret;
        if (isDebug()) {
            clientId = CLIENT_ID_DEBUG;
            clientSecret = CLIENT_SECRET_DEBUG;
        } else {
            clientId = CLIENT_ID;
            clientSecret = CLIENT_SECRET;
        }

        GoogleAuthorizationCodeFlow flow =
            new GoogleAuthorizationCodeFlow.Builder(
                TRANSPORT,
                JSON_FACTORY,
                clientId,
                clientSecret,
                SCOPES)
                .setAccessType("online")
                .setApprovalPrompt("auto")
                .build();

        return flow;
    }

    /**
     * OAuth認証のリダイレクト先を取得
     */
    private String getRedirectURL() {
        String redirectUri;
        if (isDebug()) {
            redirectUri = REDIRECT_URI_DEBUG;
        } else {
            redirectUri = REDIRECT_URI;
        }

        return redirectUri;
    }

    /**
     * OAuth認証/スタート
     */
    @ActionPath("loginOAuth")
    public Navigation loginOAuth() {

        GoogleAuthorizationCodeFlow flow = getFlow();
        String redirectUri = getRedirectURL();

        String url =
            flow.newAuthorizationUrl().setRedirectUri(redirectUri).build();

        return redirect(url);
    }

    /**
     * OAuth認証/コールバック
     */
    @ActionPath("oauth2callback")
    public Navigation oauth2callback() {
        String code = request.getParameter("code");

        GoogleAuthorizationCodeFlow flow = getFlow();
        String redirectUri = getRedirectURL();

        try {

            GoogleTokenResponse response =
                flow
                    .newTokenRequest(code)
                    .setRedirectUri(redirectUri)
                    .execute();
            GoogleCredential credential =
                new GoogleCredential().setFromTokenResponse(response);

            credentialService.save(credential);

        } catch (Exception e) {
            e.printStackTrace();
            writeResponse(e.getMessage());
            return null;
        }

        return redirect("/spreadsheet");
    }

    /**
     * スプレッドシートテスト
     * 
     * @return
     */
    @ActionPath("spreadsheet")
    public Navigation spreadsheet() {
        try {

            GoogleCredential credential = credentialService.load();
            if (credential == null) {
                return redirect("loginOAuth");
            }

            SpreadsheetService service = new SpreadsheetService(SERVICE_NAME);
            service.setOAuth2Credentials(credential);

            String key = "<スプレッドシートのKey>";
            URL entryUrl =
                new URL("https://spreadsheets.google.com/feeds/spreadsheets/"
                    + key);
            SpreadsheetEntry spreadsheetEntry =
                service.getEntry(entryUrl, SpreadsheetEntry.class);

            // 検索対象のワークシートを取得
            WorksheetEntry worksheetEntry =
                spreadsheetEntry.getDefaultWorksheet();

            // ワークシート内を検索
            URL listFeedUrl = worksheetEntry.getListFeedUrl();
            ListFeed listFeed = service.getFeed(listFeedUrl, ListFeed.class);

            // ワークシートの内容を表示
            String ret = "";
            for (ListEntry row : listFeed.getEntries()) {
                for (String tag : row.getCustomElements().getTags()) {
                    ret += row.getCustomElements().getValue(tag) + "\t";
                }
                ret += "\n";
            }
            writeResponse(ret);

        } catch (Exception e) {
            // ここ超テキトー
            e.printStackTrace();
            credentialService.delete();
            writeResponse(e.getMessage());
        }

        return null;
    }
}

CredentialData.java
package test.model;

import java.io.Serializable;

import org.slim3.datastore.Attribute;
import org.slim3.datastore.Model;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.users.User;

@Model(schemaVersion = 1)
public class CredentialData implements Serializable {

    private static final long serialVersionUID = 1L;

    @Attribute(primaryKey = true)
    private Key key;

    @Attribute(version = true)
    private Long version;

    private String accessToken;

    private User user;

    /** ------- Setter/Getter -------------------------------------- **/

    public Key getKey() {
        return key;
    }

    public void setKey(Key key) {
        this.key = key;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }


    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }
}

CredentialDataService.java
package test.service;

import java.util.List;

import org.slim3.datastore.Datastore;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

import test.meta.CredentialDataMeta;
import test.model.CredentialData;

public class CredentialDataService {

    private CredentialDataMeta t = new CredentialDataMeta();

    /**
     * OAuth証明情報を保存する
     * 
     * @param credential
     *            OAuth証明情報
     */
    public void save(GoogleCredential credential) {
        Transaction tx = Datastore.beginTransaction();

        if (load() != null) {
            delete();
        }

        UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();

        CredentialData data = new CredentialData();
        data.setUser(user);
        data.setAccessToken(credential.getAccessToken());

        Datastore.put(data);
        tx.commit();
    }

    /**
     * ログインしているユーザのOAuth証明情報を削除する
     */
    public void delete() {
        UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();

        List<CredentialData> list =
            Datastore.query(t).filter(t.user.equal(user)).asList();
        for (CredentialData d : list) {
            Datastore.delete(d.getKey());
        }
    }

    /**
     * ログインしているユーザのOAuth証明情報を取得する
     * 
     * @return OAuth証明情報
     */
    public GoogleCredential load() {
        UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();

        List<CredentialData> list =
            Datastore.query(t).filter(t.user.equal(user)).asList();

        if (list.size() == 0) {
            return null;
        } else {
            String accessToken = list.get(0).getAccessToken();
            GoogleCredential credential =
                new GoogleCredential().setAccessToken(accessToken);
            return credential;
        }
    }
}

14
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
11