Wednesday, June 10, 2015

使用Google OAuth2登入並使用雲端試算表

文章攢寫時間︰2015/06/11 13:37

一、前言

自從2015年05月開始,
Google不再提供Client-Login和OAuth的方式提供開發者登入Google帳戶,
如需使用程式登入,
僅能由OAuth2的管道。

在Android裝置上要登入Google使用其服務,
Play Service已提供一個極簡易的方法︰
GoogleAuthUtil.getToken(mActivity, mEmail, mScope);

這種登入的方式雖然很簡便,
但是缺點就是「只能存取自己帳戶底下」的雲端硬碟或個人內容。
如果今天想要把SpreadSheet(試算表)當作雲端資料庫,
讓你的App能隨時來存取資料,
這個方法可能就行不通了。

二、文章開始

前一篇曾使用過Client-Login登入Google的方式來存取SpreadSheet(試算表),
今天則是介紹使用OAuth2的方式。

Google提供了相~當~多~的管道過OAuth2,
這裡僅示例Android我實際用過且work的方式 - 使用P12檔。

步驟1 在Google APIs Console建立一個新專案並做相關設定


同意畫面是顯示給使用者認證的畫面,
商品名稱一定要打上去,
並記得按下方的儲存鈕。
建立新的用戶端ID
選擇使用P12檔的登入方式
此時跳出一個畫面,
把p12檔存起來。
這即將是您登入Google使用的鑰匙。

畫面也同時看到多了一個新的登入連線方式了。

步驟2 將P12檔複製到Android Studio專案底下

在src/main底下點滑鼠右鍵,
建立一個全新的assets資料夾
(此步驟如果已有assets資料夾則無需理會)
將剛才存起來的P12檔存入。

步驟3 匯入需要的jar檔

OAuth2的登入流程相當繁鎖,
但因為Google也提供了google-oauth-java-client套件供我們走OAuth2登入,
省掉開發的時程。

這個專案需要以下的jar檔,
請下載並import。
gdata-core-1.0.jar //spreadsheet會用到
gdata-spreadsheet-3.0.jar //spreadsheet用到
google-http-client-1.18.0-rc.jar //spreadsheet用到
google-http-client-jackson-1.18.00rc.jar //spreadsheet用到
guava-11.0.2.jar //spreadsheet用到
jackson-core-asl-1.9.11.jar //spreadsheet用到

google-api-client-1.18.0-rc.jar //OAuth2會用到
google-oauth-client-1.18.0-rc.jar //OAuth2會用到

步驟4 開始攢寫程式

走OAuth2時,
告知Google我們要存取什麼範圍(SCOPE)的content,
就可由底下的程式範例做登入動作了。
HttpTransport httpTransport = new NetHttpTransport();
                JacksonFactory jsonFactory = new JacksonFactory();

                ArrayList SCOPES = new ArrayList();
                SCOPES.add("https://spreadsheets.google.com/feeds");

                //SerServiceAcountId: clientID value should be similar to @developer.gserviceaccount.com They basically expect the email_address value from the console api credentials
                GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport).setJsonFactory(jsonFactory)
                        .setServiceAccountId("填入剛才新增用戶端ID得到的Mail")
                        .setServiceAccountPrivateKeyFromP12File(getTempPkc12File())
                        .setServiceAccountUser("欲分享SpreadSheet的人的gmail")
                        .setServiceAccountScopes(SCOPES)
                        .build();

                credential.refreshToken();

                String accessToken = credential.getAccessToken();
                Log.i(TAG, "accessToken: "+accessToken);

getTempPkc12File()函式內容如下,
記得更改掉open()裡的P12檔檔名。
        private File getTempPkc12File() throws IOException {
            InputStream pkc12Stream = mContext.getAssets().open("ScalpTest-1a66d0dc35fe.p12");//記得將檔名改成剛才存進Assets資料夾裡的P12檔檔名
            File tempPkc12File = File.createTempFile("P12File", "p12");
            OutputStream tempFileStream = new FileOutputStream(tempPkc12File);

            int read = 0;
            byte[] bytes = new byte[1024];
            while ((read = pkc12Stream.read(bytes)) != -1) {
                tempFileStream.write(bytes, 0, read);
            }
            return tempPkc12File;
        }

如果要使用SpreadSheet API,
這裡提供整份程式碼示例
List<spreadsheetentry> spreadsheets = null;

            SpreadsheetService mSpreadSheetService = new SpreadsheetService("欲存取的資料表名稱");
            mSpreadSheetService.setProtocolVersion(SpreadsheetService.Versions.V3);
            try {
                //2015/05月已停止使用
//                mSpreadSheetService.setUserCredentials("xxx@gmail.com", "密碼");

                HttpTransport httpTransport = new NetHttpTransport();
                JacksonFactory jsonFactory = new JacksonFactory();

                ArrayList SCOPES = new ArrayList();
                SCOPES.add("https://spreadsheets.google.com/feeds");

                //SerServiceAcountId: clientID value should be similar to @developer.gserviceaccount.com They basically expect the email_address value from the console api credentials
                GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport).setJsonFactory(jsonFactory)
                        .setServiceAccountId("填入剛才新增用戶端ID得到的Mail")
                        .setServiceAccountPrivateKeyFromP12File(getTempPkc12File())
                        .setServiceAccountUser("xxx@gmail.com")
                        .setServiceAccountScopes(SCOPES)
                        .build();

                credential.refreshToken();

                String accessToken = credential.getAccessToken();
                Log.i(TAG, "accessToken: "+accessToken);

                mSpreadSheetService.setOAuth2Credentials(credential);

                URL url = new URL("https://spreadsheets.google.com/feeds/spreadsheets/private/full");

                SpreadsheetFeed spreadFeed = mSpreadSheetService.getFeed(url, SpreadsheetFeed.class);
                spreadsheets = spreadFeed.getEntries();

三、結論

以上介紹了使用P12檔過Google OAuth2的方式。
如果是Server則又有各自不同的登入方式,
就交給大家去研究了。

相關文章

1. 官方OAuth2ForDevices
2. 官方OAuth2InstalledApp
3. 官方OAuth2介紹
4. 使用試算表API

取得user-code
curl -d "client_id=855763605695-nn0a0tv8k83pqq28trtfckfhf8och19t.apps.googleusercontent.com&scope=https://spreadsheets.google.com/feeds" https://accounts.google.com/o/oauth2/device/code

RESPONSE:
{
  "device_code" : "LDBE-ZXPU4/wyoUadofXRCeslItAym9DJvQAt8fS8mFvlGUk9a5Ix4",
  "user_code" : "LDBE-ZXPU",
  "verification_url" : "https://www.google.com/device",
  "expires_in" : 1800,
  "interval" : 5
}
==============================
取得accessToken
curl -d "client_id=855763605695-nn0a0tv8k83pqq28trtfckfhf8och19t.apps.googleusercontent.com&client_secret=yz2SJO7DrYSxEwEYGA6xcjIl&code=LDBE-ZXPU4/wyoUadofXRCeslItAym9DJvQAt8fS8mFvlGUk9a5Ix4&grant_type=http://oauth.net/grant_type/device/1.0" https://www.googleapis.com/oauth2/v3/token


https://accounts.google.com/o/oauth2/auth?
  scope=email%20profile&
  redirect_uri=urn:ietf:wg:oauth:2.0:oob&
  response_type=code&
  client_id=855763605695-nn0a0tv8k83pqq28trtfckfhf8och19t.apps.googleusercontent.com