java - 几个小时后,Google 表格 java sdk oAuth 未经授权( Spring 启动)

标签 java spring-boot google-sheets-api

我成功地创建了一个 spring boot Serviceclass 以便在 google 表格上写,遵循 Java Quistart Tutorial for Sheets API

我的问题是授权没有更新,所以在第一次通过浏览器成功验证后,几个小时后我得到 401 unauthorized。 如何在不重新发布浏览器登录的情况下自动更新 token ?

下面是代码,在此先感谢

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver.Builder;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.SheetsScopes;
import com.google.api.services.sheets.v4.model.AppendValuesResponse;
import com.google.api.services.sheets.v4.model.ValueRange;

@Service
public class GoogleSheetsServiceImpl implements GoogleSheetsService {

    private static final Log LOGGER = LogFactory.getLog(GoogleSheetsServiceImpl.class);

    /** Application name. */
    @Value("${google-sheets.application-name}")
    private String applicationName;

    /** Directory to store user credentials for this application. */
    private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"),
            ".credentials/sheets.googleapis.com-orders");

    /** Global instance of the {@link FileDataStoreFactory}. */
    private FileDataStoreFactory dataStoreFactory;

    /** Global instance of the JSON factory. */
    private JsonFactory jsonFactory;

    /** Global instance of the HTTP transport. */
    private HttpTransport httpTransport;

    /**
     * Global instance of the scopes required by this quickstart.
     *
     * If modifying these scopes, delete your previously saved credentials at
     * ~/.credentials/sheets.googleapis.com-java-quickstart
     */
    private List<String> scopes;

    /** Sheet service. */
    private Sheets sheetsService;

    public GoogleSheetsServiceImpl() throws Throwable {
        // init
        try {
            this.jsonFactory = JacksonFactory.getDefaultInstance();
            this.scopes = Arrays.asList(SheetsScopes.SPREADSHEETS);
            this.httpTransport = GoogleNetHttpTransport.newTrustedTransport();
            this.dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
        } catch (Throwable t) {
            LOGGER.error("Error on init Google Sheets Service: " + t.getMessage());
            throw t;
        }

        // get sheet service
        Credential credential = this.authorize();
        this.sheetsService = new Sheets.Builder(this.httpTransport, this.jsonFactory, credential)
                .setApplicationName(this.applicationName).build();
    }

    public void appendValueRangeToGoogleSheet(String spreadsheetId, String range, ValueRange valueRange)
            throws IOException {

        // append line
        Sheets.Spreadsheets.Values.Append request = sheetsService.spreadsheets().values()
                .append(spreadsheetId, range, valueRange).setValueInputOption("RAW");
        AppendValuesResponse response = request.execute();
    }

    /**
     * Creates an authorized Credential object.
     * 
     * @return an authorized Credential object.
     * @throws IOException
     */
    private Credential authorize() throws IOException {
        // Load client secrets.
        InputStream in = GoogleSheetsServiceImpl.class.getResourceAsStream("/google_sheets/client_secret.json");
        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(this.jsonFactory, new InputStreamReader(in));

        // Build flow and trigger user authorization request.
        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(this.httpTransport, this.jsonFactory,
                clientSecrets, this.scopes).setDataStoreFactory(this.dataStoreFactory).setAccessType("online").build();
        LocalServerReceiver.Builder localServerReceiverBuilder = new Builder();
        localServerReceiverBuilder.setHost("localhost");
        localServerReceiverBuilder.setPort(46228);
        Credential credential = new AuthorizationCodeInstalledApp(flow, localServerReceiverBuilder.build())
                .authorize("user");
        LOGGER.info("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
        return credential;
    }

}

编辑:

解决了如下修改 GoogleAuthorizationCodeFlow 对象的构建问题:

GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(this.httpTransport, this.jsonFactory,
            clientSecrets, this.scopes).setDataStoreFactory(this.dataStoreFactory).setAccessType("offline")
                    .setApprovalPrompt("force")
                    .addRefreshListener(
                            new DataStoreCredentialRefreshListener(credentialUserId, this.dataStoreFactory))
                    .build();

最佳答案

有一个概念叫做refresh token,看起来很适合你的需求。

你可以在这个问题中找到很好的描述: https://stackoverflow.com/a/7209263/4988996

编辑:根据您的评论,我发现谷歌有 DataStoreCredentialRefreshListener

Access protected resources using the Credential. Expired access tokens are automatically refreshed using the refresh token, if applicable. Make sure to use DataStoreCredentialRefreshListener and set it for the credential using Credential.Builder.addRefreshListener(CredentialRefreshListener).

结帐:https://developers.google.com/api-client-library/java/google-oauth-java-client/oauth2

  static void addDataStoreCredentialRefreshListener(
      Credential.Builder credentialBuilder, String userId, DataStoreFactory dataStoreFactory)
      throws IOException {
    credentialBuilder.addRefreshListener(
        new DataStoreCredentialRefreshListener(userId, dataStoreFactory));
  }

关于java - 几个小时后,Google 表格 java sdk oAuth 未经授权( Spring 启动),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46705204/

相关文章:

java - 图像模糊的简单指标?

java - 将金钱转换成所有可能的组合

java - JBOSS 7 域 jsp 更改重新启动后未反射(reflect)

spring-boot - Gradle 多模块项目 java.lang.NoClassDeffFoundError

java - 将带有 jackson 的嵌套 json 映射到 java 字段

google-apps-script - Google Sheets 脚本和 Google Sheets API 有什么区别?

c# - 如何使用 C# 和 Sheet Api 访问和插入数据到 Google Spread Sheet?

java - 为什么我的空检查这么慢?

java - 服务器端加载资源失败

python - 在 Python 中迭代和打印 JSON 对象