2012-05-09 67 views
3

我試圖使用Service Account方法訪問Google BigQuery。我的代碼如下:BigQuery和OAuth2

private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); 

private static final JsonFactory JSON_FACTORY = new JacksonFactory(); 

GoogleCredential credentials = new GoogleCredential.Builder() 
      .setTransport(HTTP_TRANSPORT) 
      .setJsonFactory(JSON_FACTORY) 
      .setServiceAccountId("[email protected]") 
      .setServiceAccountScopes(BigqueryScopes.BIGQUERY) 
      .setServiceAccountPrivateKeyFromP12File(
        new File("PATH-TO-privatekey.p12")) 
      .build(); 
    Bigquery bigquery = Bigquery.builder(HTTP_TRANSPORT, JSON_FACTORY).setHttpRequestInitializer(credentials) 
      .build(); 
    com.google.api.services.bigquery.Bigquery.Datasets.List datasetRequest = bigquery.datasets().list(
      "PROJECT_ID"); 

    DatasetList datasetList = datasetRequest.execute(); 
    if (datasetList.getDatasets() != null) { 
     java.util.List<Datasets> datasets = datasetList.getDatasets(); 
     System.out.println("Available datasets\n----------------"); 
     for (Datasets dataset : datasets) { 
      System.out.format("%s\n", dataset.getDatasetReference().getDatasetId()); 
     } 
    } 

但它拋出以下異常:

Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized 
{ 
    "code" : 401, 
    "errors" : [ { 
    "domain" : "global", 
    "location" : "Authorization", 
    "locationType" : "header", 
    "message" : "Authorization required", 
    "reason" : "required" 
    } ], 
    "message" : "Authorization required" 
} 
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:159) 
at com.google.api.client.googleapis.json.GoogleJsonResponseException.execute(GoogleJsonResponseException.java:187) 
at com.google.api.client.googleapis.services.GoogleClient.executeUnparsed(GoogleClient.java:115) 
at com.google.api.client.http.json.JsonHttpRequest.executeUnparsed(JsonHttpRequest.java:112) 
at com.google.api.services.bigquery.Bigquery$Datasets$List.execute(Bigquery.java:979) 

唯一的例外是在這條線觸發:

DatasetList datasetList = datasetRequest.execute(); 

我從獲取帳戶ID谷歌的API控制檯上的第二行顯示如下:

Client ID: XXXXX.apps.googleusercontent.com 
    Email address: [email protected] 

我錯過了什麼?

回答

1

編輯:下面給出的答案與使用Google App Engine服務帳戶相關 - 此處僅供參考。

仔細檢查您是否已將您的服務帳戶地址作爲所有者添加到項目的團隊頁面。

我建議使用AppIdentityCredential類來處理服務帳戶身份驗證。這裏有一小段代碼演示了這一點,我將在BigQuery API開發者頁面上添加關於此的附加文檔。此外,請確保您使用的是最新版本的Google Java API客戶端(截至今日,其版本爲「v2-rev5-1.5.0-beta」here)。

import java.io.IOException; 

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

import com.google.api.client.googleapis.extensions.appengine.auth.oauth2.AppIdentityCredential; 
import com.google.api.client.http.HttpTransport; 
import com.google.api.client.http.javanet.NetHttpTransport; 
import com.google.api.client.http.json.JsonHttpRequest; 
import com.google.api.client.http.json.JsonHttpRequestInitializer; 
import com.google.api.client.json.JsonFactory; 
import com.google.api.client.json.jackson.JacksonFactory; 
import com.google.api.services.bigquery.Bigquery; 
import com.google.api.services.bigquery.BigqueryRequest; 

@SuppressWarnings("serial") 
public class Bigquery_service_accounts_demoServlet<TRANSPORT> extends HttpServlet { 

// ENTER YOUR PROJECT ID HERE 
private static final String PROJECT_ID = ""; 

private static final HttpTransport TRANSPORT = new NetHttpTransport(); 
private static final JsonFactory JSON_FACTORY = new JacksonFactory(); 
private static final String BIGQUERY_SCOPE = "https://www.googleapis.com/auth/bigquery"; 


AppIdentityCredential credential = new AppIdentityCredential(BIGQUERY_SCOPE); 
Bigquery bigquery = Bigquery.builder(TRANSPORT,JSON_FACTORY) 

.setHttpRequestInitializer(credential) 
.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() { 
    public void initialize(JsonHttpRequest request) { 
    BigqueryRequest bigqueryRequest = (BigqueryRequest) request; 
    bigqueryRequest.setPrettyPrint(true); 
    } 
}).build();  

public void doGet(HttpServletRequest req, HttpServletResponse resp) 
    throws IOException { 
    resp.setContentType("text/plain"); 
    resp.getWriter().println(bigquery.datasets() 
    .list(PROJECT_ID) 
    .execute().toString()); 
} 
} 
+0

感謝您的快速反應,但它不工作。我正在使用最新的BigQuery API二進制文件(您指出的那個); google-api-client是它的依賴,它的版本是1.8.0-beta。根據此http://javadoc.google-api-java-client.googlecode.com/hg/1.8.0-beta/com/google/api/client/googleapis/extensions/appengine/auth/oauth2/AppIdentityCredential.html該類應該是其中的一部分,但它不是。我在這裏查看maven central的二進制文件和源代碼:http://search.maven.org/#artifactdetails|com.google.api-client|google-api-client|1.8.0-betajjar。 – ediaz

-1

這是一個完整的片段供參考:

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.jackson.JacksonFactory; 

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; 
import com.google.api.services.bigquery.Bigquery; 
import com.google.api.services.bigquery.Bigquery.Datasets; 
import com.google.api.services.bigquery.model.DatasetList; 

import java.io.File; 
import java.io.IOException; 
import java.security.GeneralSecurityException; 


public class BigQueryJavaServiceAccount { 

    private static final String SCOPE = "https://www.googleapis.com/auth/bigquery"; 
    private static final HttpTransport TRANSPORT = new NetHttpTransport(); 
    private static final JsonFactory JSON_FACTORY = new JacksonFactory(); 

    public static void main(String[] args) throws IOException, GeneralSecurityException { 
    GoogleCredential credential = new GoogleCredential.Builder().setTransport(TRANSPORT) 
     .setJsonFactory(JSON_FACTORY) 
     .setServiceAccountId("[email protected]") 
     .setServiceAccountScopes(SCOPE) 
     .setServiceAccountPrivateKeyFromP12File(new File("my_file.p12")) 
     .build(); 

    Bigquery bigquery = Bigquery.builder(TRANSPORT, JSON_FACTORY) 
     .setApplicationName("Google-BigQuery-App/1.0") 
     .setHttpRequestInitializer(credential).build(); 

    Datasets.List datasetRequest = bigquery.datasets().list("publicdata"); 
    DatasetList datasetList = datasetRequest.execute(); 
    System.out.format("%s\n", datasetList.toPrettyString()); 
} 
+0

我試着用相同的結果,不僅我添加了這個:System.out.println(BigqueryScopes.BIGQUERY);我得到了這個值:https://www.googleapis.com/auth/bigquery,所以範圍url是正確的。 – ediaz

+0

@ediaz:Google Java API客戶端lib當前未在客戶端構建()步驟中傳遞特定的OAuth錯誤。您可以通過在您的Eclipse運行配置中爲VM參數添加此參數來啓用所有HTTP請求的控制檯輸出: -Djava.util.logging.config.file =/tmp/javalogging.properties 您的「/ tmp/javalogging的.properties」文件應包含以下內容: 處理器= java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level = CONFIG com.google.api.client.http.level = CONFIG –

+0

請訪問http: //code.google.com/p/google-api-java-client/source/browse/buzz-v1-json-oauth2-cmdline-sample/logging.properties?repo=samples&r=f3e5812b26fa8963028ba6ba5db43cfa93e97c53瞭解更多信息 –

5

尤里卡!埃裏克和邁克爾的代碼運作良好。

發佈在問題中的錯誤可以通過錯誤地設置客戶機上的時間來重現。幸運的是,它可以通過正確設置客戶機上的時間來解決

注意:對於它的價值,我使用「Internet時間設置」對話框中的「立即更新」按鈕將時間同步到Windows 7盒子上。我想這應該是非常愚蠢的證明......但我想我擊敗了系統。它校正了秒數,但是將機器關閉了一分鐘。之後,BigQuery調用失敗。我手動更改時間後成功了。

2

我們在Java庫中的錯誤處理代碼需要改進一點!

它看起來像簽署的JWT請求OAuth訪問令牌失敗。你可以通過啓用@MichaelManoochehri上面提到的日誌來看到這一點。

,我認爲

這裏只有幾件事情可能是造成這種故障:

  1. 無效的簽名(用錯了鑰匙)
  2. 無效的電子郵件地址服務帳戶(我認爲這被排除出)
  3. 無效的日期/時間用於生成簽署BLOB(一期日期,到期日期)
  4. 無效的範圍(我認爲這就是被排除在外)
郵票

您應該檢查您的日期/時間是否在服務器上正確設置了適當的時區 - 與NTP同步。您可以使用time.gov查看官方美國原子鐘時間。