如何从Java中使用服务帐户访问Google表格?

huangapple go评论77阅读模式
英文:

How do you access a Google Sheet with a service account from Java?

问题

我正在尝试从服务帐户中访问Google表格(服务帐户具有对表格的访问权限)。但是我遇到了一个问题,包括官方文档在内的所有文档都指向使用已自1.7版起被弃用的GoogleCredential。弃用说明指出,您应该使用库google-auth-library,这就是我在以下代码中所做的:

val googleCredentials = ServiceAccountCredentials
      .fromStream(new FileInputStream(CREDENTIALS_FILE_PATH))
      .createScoped(SCOPES)
googleCredentials.refresh()

但是变量的类型是GoogleCredentials,而函数Sheets.Builder不接受此类型作为有效的HttpRequestInitializer。因此,我不得不通过以下使用弃用类的方式进行一些变通:

val token = googleCredentials.getAccessToken.getTokenValue
val credential = new GoogleCredential().setAccessToken(token)

通过这种变通方法,我能够访问Google表格,但我确信有一种更合适的方法可以在不使用弃用库的情况下实现。

有人知道正确的方法是什么吗?

以下是完整代码片段,以供参考。

package drivers
import java.io.FileInputStream
import java.util.Collections

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
import com.google.api.client.json.jackson2.JacksonFactory
import com.google.api.services.sheets.v4.{Sheets, SheetsScopes}
import com.google.auth.oauth2.ServiceAccountCredentials
import com.typesafe.config.ConfigFactory

object TestDriver {

  def main(args: Array[String]): Unit = {
    val config = ConfigFactory.load()
    val spreadsheetId = config.getString("spreadsheetId")
    val CREDENTIALS_FILE_PATH = config.getString("google_application_credentials")

    val SCOPES = Collections.singletonList(SheetsScopes.SPREADSHEETS_READONLY)
    val JSON_FACTORY = JacksonFactory.getDefaultInstance
    val APPLICATION_NAME = "my-app"

    val googleCredentials = ServiceAccountCredentials
      .fromStream(new FileInputStream(CREDENTIALS_FILE_PATH))
      .createScoped(SCOPES)
    googleCredentials.refresh()

    val token = googleCredentials.getAccessToken.getTokenValue
    val credential = new GoogleCredential().setAccessToken(token)
    val httpTransport = GoogleNetHttpTransport.newTrustedTransport
    val service = new Sheets.Builder(httpTransport, JSON_FACTORY, credential)
      .setApplicationName(APPLICATION_NAME)
      .build()
    val range = "Sheet1!A1:D1"
    val response = service.spreadsheets().values().get(spreadsheetId, range).execute()
    val values = response.getValues
    values.forEach(println)
  }
}
英文:

I'm trying to access a Google Sheet from a service account (the service account has access to the sheet). But I have a problem, all the documentation including the official docs point to use GoogleCredential that is deprecated since 1.7. The deprecation says that you sould use library google-auth-library and this is what I'm doing in:

val googleCredentials = ServiceAccountCredentials
      .fromStream(new FileInputStream(CREDENTIALS_FILE_PATH))
      .createScoped(SCOPES)
googleCredentials.refresh()

but the variable is of type GoogleCredentials and the function Sheets.Builder doesn't accept this as a valid HttpRequestInitializer. So I had to hack my way around using the deprecated class with:

val token = googleCredentials.getAccessToken.getTokenValue
val credential = new GoogleCredential().setAccessToken(token)

With this workaround I'm able to access the Google Sheet but I'm sure that there is a proper way to do it without using deprecated libraries.

Does anyone know what's the proper way to do it?

Leaving here the full snippet as a reference.

package drivers
import java.io.FileInputStream
import java.util.Collections

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
import com.google.api.client.json.jackson2.JacksonFactory
import com.google.api.services.sheets.v4.{Sheets, SheetsScopes}
import com.google.auth.oauth2.ServiceAccountCredentials
import com.typesafe.config.ConfigFactory

object TestDriver {

  def main(args: Array[String]): Unit = {
    val config = ConfigFactory.load()
    val spreadsheetId = config.getString("spreadsheetId")
    val CREDENTIALS_FILE_PATH = config.getString("google_application_credentials")

    val SCOPES = Collections.singletonList(SheetsScopes.SPREADSHEETS_READONLY)
    val JSON_FACTORY = JacksonFactory.getDefaultInstance
    val APPLICATION_NAME = "my-app"

    val googleCredentials = ServiceAccountCredentials
      .fromStream(new FileInputStream(CREDENTIALS_FILE_PATH))
      .createScoped(SCOPES)
    googleCredentials.refresh()

    val token = googleCredentials.getAccessToken.getTokenValue
    val credential = new GoogleCredential().setAccessToken(token)
    val httpTransport = GoogleNetHttpTransport.newTrustedTransport
    val service = new Sheets.Builder(httpTransport, JSON_FACTORY, credential)
      .setApplicationName(APPLICATION_NAME)
      .build()
    val range = "Sheet1!A1:D1"
    val response = service.spreadsheets().values().get(spreadsheetId, range).execute()
    val values = response.getValues
    values.forEach(println)
  }

答案1

得分: 3

  • 信息混淆,Google Auth Library推荐使用的,因为已弃用的部分包括 google-auth-library-oauth2 库。
  • 换句话说,您仍然可以使用 GoogleCredential,并且仍然是文档中推荐的方法:
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(CREDENTIALS_FILE_PATH))
.createScoped(Collections.singleton(SCOPES));
  • 或者,您还可以从 .p12 文件构建凭据:
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(emailAddress)
.setServiceAccountPrivateKeyFromP12File(new File("MyProject.p12"))
.setServiceAccountScopes(Collections.singleton(YOUR SCOPE))
.build();
  • 但是,如果您确实想要使用 GoogleCredentials 并且在 HttpRequestInitializer 方面遇到问题,您可以使用HttpCredentialsAdapter
英文:
  • The information is confusing, the Google Auth Library that is recommended to use since the deprecation includes the google-auth-library-oauth2 library
  • In other words, you can still use GoogleCredential, and it is still the method recommended in the documentation:
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(CREDENTIALS_FILE_PATH))
.createScoped(Collections.singleton(SCOPES));
  • Alternatively, you can also build your credential from a .p12 file:
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(emailAddress)
.setServiceAccountPrivateKeyFromP12File(new File("MyProject.p12"))
.setServiceAccountScopes(Collections.singleton(YOUR SCOPE))
.build();
  • However, if you do want to use GoogleCredentials and have problems with the HttpRequestInitializer you can use the HttpCredentialsAdapter

huangapple
  • 本文由 发表于 2020年9月30日 18:33:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/64135720.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定