2012-05-09 3 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를 얻고있다 두 번째 줄의 섹션에서 Google의 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-beta|jar. – 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 클라이언트 라이브러리는 현재 클라이언트 빌드() 단계에서 특정 OAuth 오류를 전달하지 않습니다.-Djava.util.logging.config.file =/tmp/javalogging.properties "/ tmp/javalogging"을 사용하여 모든 HTTP 요청의 콘솔 출력을 Eclipse 실행 구성의 VM 인수에 추가로 설정할 수 있습니다. .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

유레카! Eric과 Michael의 코드가 잘 작동합니다.

질문에 게시 된 오류는 클라이언트 컴퓨터의 시간을 잘못 설정하여 재현 할 수 있습니다. 다행히도 은 클라이언트 컴퓨터의 시간을 올바르게 설정하여 해결할 수 있습니다.

참고 : "인터넷 시간 설정"대화 상자의 "지금 업데이트"버튼을 사용하여 Windows 7 상자에서 시간을 동기화했습니다. 나는 그것이 꽤 바보 같은 증거가 될 것이라고 생각했다. 그러나 나는 그 시스템을 때려 눕혔다. 그것은 초를 수정했지만 기계를 정확히 1 분 남겨 둡니다. 그 후에 BigQuery 호출이 실패했습니다. 수동으로 시간을 변경 한 후에 성공했습니다.

2

자바 라이브러리의 오류 처리 코드가 약간 개선되어야합니다!

OAuth 액세스 토큰을 요청하는 데 서명 된 JWT가 실패한 것으로 보입니다. @MichaelManoochehri가 위에서 언급 한 로그를 활성화하면이를 볼 수 있습니다.

  1. 잘못된 서명 (잘못된 키를 사용하여) 서비스 계정 (나는 그 지배 한 생각에 대한
  2. 잘못된 이메일 주소 : 내가 생각

    있습니다 만 몇 가지가이 고장의 원인이 될 수있다 서명 된 BLOB (문제의 날짜 및 만료 날짜)

  3. 잘못된 범위를 (I 배제 된 사용자들은 생각)
생성에 사용되는 아웃)
  • 잘못된 날짜/시간 스탬프

    NTP에 적절한 시간대를 사용하여 서버에 날짜/시간이 올바르게 설정되어 있는지 확인해야합니다. time.gov를 사용하여 미국의 공식 시계를 볼 수 있습니다.