gpt4 book ai didi

java - 如何使用服务帐户从 App Engine 访问 Google 电子表格?

转载 作者:搜寻专家 更新时间:2023-11-01 03:24:50 26 4
gpt4 key购买 nike

我在 Google App Engine 上有一个应用程序(托管在 appspot.com 上),一些用户将使用它从互联网上抓取一些东西,将其保存在数据存储中,然后将其写入 Google 电子表格。我想使用服务帐户访问电子表格,但无论我是否尝试使用 Drive API 创建文件,当我尝试执行任何操作时都遇到了 400 OK { "error": "invalid_grant"} 问题或使用 Spreadsheets API 访问现有文件。

我在 API 控制台中同时启用了 Drive API 和 Drive SDK,并生成了一个 P12 key 。这是我构建 GoogleCredential 的方法:

private GoogleCredential getGoogleCredential() throws IOException, GeneralSecurityException {
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(TRANSPORT)
.setJsonFactory(FACTORY)
.setServiceAccountId("1511XXX90247.apps.googleusercontent.com")
.setServiceAccountScopes(scopes)
.setServiceAccountPrivateKeyFromP12File(
new File("05a605b0fXXXd2a6be864be15d81a2bd629d3bd6-privatekey.p12"))
.setServiceAccountUser("XXX@gmail.com") // My personal e-mail address which I used to create the project
.build();
return credential;
}

ServiceAccountID 来自 API 控制台。我试过使用 1511XXX90247@developer.gserviceaccount.com 作为我的 ServiceAccountUser 以及 myappname@appspot.gserviceaccount.com。我使用的范围如下:

https://spreadsheets.google.com/feeds
https://docs.google.com/feeds
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/drive.file

这是我尝试使用 Spreadsheets API 时失败的代码:

        SpreadsheetService service = new SpreadsheetService("name of my app");
service.setOAuth2Credentials(getGoogleCredential());
FeedURLFactory factory = FeedURLFactory.getDefault();
SpreadsheetQuery query = new SpreadsheetQuery(factory.getSpreadsheetsFeedUrl());
query.setTitleQuery("test");
SpreadsheetFeed feed = service.query(query, SpreadsheetFeed.class);

当服务尝试执行查询时代码失败。

这是我尝试过但也失败的云端硬盘代码:

        Drive drive = new Drive.Builder(TRANSPORT, FACTORY,
getGoogleCredential()).build();
com.google.api.services.drive.model.File file = new com.google.api.services.drive.model.File();
file.setTitle("test");
file.setMimeType("application/vnd.google-apps.spreadsheet");
drive.files().insert(file).execute(); // This is where the code fails

无论我尝试什么,我似乎总是以同样的“无效授予”错误告终。这是部分堆栈跟踪:

com.google.gdata.util.AuthenticationException: Failed to refresh access token: 400 OK { "error" : "invalid_grant" } 
at com.google.gdata.client.GoogleAuthTokenFactory$OAuth2Token.refreshToken(GoogleAuthTokenFactory.java:260)
at com.google.gdata.client.GoogleAuthTokenFactory.handleSessionExpiredException(GoogleAuthTokenFactory.java:702)
at com.google.gdata.client.GoogleService.handleSessionExpiredException(GoogleService.java:738) at com.google.gdata.client.GoogleService.getFeed(GoogleService.java:680)
at com.google.gdata.client.Service.query(Service.java:1237)
at com.google.gdata.client.Service.query(Service.java:1178)
at spam.gwt.scraper.server.spreadsheets.APIConnector.doGet(APIConnector.java:66)

我试图到处寻找答案,包括但不限于 Google Developers Spreadsheets Guide , 这个Service Account-related Stack Overflow question还有这个Google App Engine-specific Stack Overflow question .随着发展(例如 Docs -> Drive),很难找到最新的信息,更不用说专门与 GAE 相关的信息了。

最佳答案

我使用 App Engine 应用程序的内置服务帐户,而不是创建自己的服务帐户;这样就保存了私钥(不存储在本地,只存储在应用引擎上)。

对于云端硬盘:

    protected Drive createDriveService() throws BookingSheetException {

HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleClientRequestInitializer keyInitializer =
new CommonGoogleClientRequestInitializer(API_KEY);
AppIdentityCredential credential =
new AppIdentityCredential.Builder(Arrays.asList(DriveScopes.DRIVE)).build();
Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential)
.setGoogleClientRequestInitializer(keyInitializer)
.setApplicationName(appname).build();
return service;
}

对于电子表格:

private Credential creds;
/**
* Keep the expiration time of the access token to renew it before expiry
*/
private Calendar expirationTime = Calendar.getInstance();
protected void initCredentials() {
List<String> scopes = Arrays.asList("https://spreadsheets.google.com/feeds");
AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();
AppIdentityService.GetAccessTokenResult accessToken = appIdentity.getAccessToken(scopes);
expirationTime.setTime(accessToken.getExpirationTime());
expirationTime.add(Calendar.MINUTE,-REFRESH_MINUTES); //refresh some time before expiry
creds = new Credential(BearerToken.authorizationHeaderAccessMethod());
creds.setAccessToken(accessToken.getAccessToken());
}

public SpreadsheetUtil(String appname) {
myService = new SpreadsheetService(appname);
myService.setOAuth2Credentials(cred);
}

确保 creds.refreshToken() 或在它们过期时重新初始化。

关于java - 如何使用服务帐户从 App Engine 访问 Google 电子表格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17380739/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com