- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我成功地创建了一个 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/
据我所知,要将声音设置为铃声,应将其插入 MediaStore。在 MediaStore 中写入,需要 WRITE_EXTERNAL_STORAGE 权限。但是...有没有办法在不需要 WRITE_E
我只是想设置铃声。我不想授予 WRITE_SETTINGS 权限,我可以找到大部分答案来授予 WRITE_SETTINGS 权限但是我正在使用一个应用程序,该应用程序没有设置铃声的 WRITE_SET
我在 Windows 10 中以管理员身份运行 Android studio。AVD 是 Nexus 5X API 28。我正在尝试运行 flutter 演示,但设备下拉框仍然显示“无设备”,它只是有
我的应用程序构建于 spring-social-twitter允许用户使用 Twitter 登录的功能最近已停止工作。 我收到如下错误消息: Callback URL not approved for
我正在尝试使用 python-firebase 更新 Firebase库,但无法使用经过修改的示例代码进行身份验证: from firebase import firebase as fb auth
今天,当我尝试使用 GCC7 编译一个非常简单的 C++ 程序时,我遇到了一个非常奇怪的问题:程序没有向构造函数中的 vector 添加任何元素,当编译时没有优化(例如 -O0/-Og ) 来自 Re
简单问题:我正在尝试使用 Discord API 备份服务器(或公会,如果您使用官方术语)上的所有消息。 因此,我实现了 OAuth,没有任何问题,我有访问 token ,并且可以查询一些端点(我尝试
您好,我正在使用 msdn 中的以下代码供我公司内部使用: using System; public sealed class Singleton { private static volati
我们从 Google 的 GCM 服务中收到间歇性的 401 Unauthorized 错误。在过去,它 100% 的时间都有效。该问题可能与我们的路由器接受 IPv6 流量同时发生,但即使我们在适配
我有一个使用 Playwright + TS-Jest 设置 E2E 测试的项目。为了组织我的测试,我使用页面对象模型。结构看起来像这样: 我想在 tsconfig.json 中使用 TypeScri
我有一个后端应用程序在 Google Cloud Storage 中同步文件,我想在 javascript 中列出存储中的所有文件,而不需要从后端请求它们。我已经设置了 CORS,并且所有文件的 ac
我在尝试在私有(private) gitlab 存储库中发布 Artifact 时遇到问题。我正在使用 Maven 并使用个人访问 token 进行身份验证。当我运行 mvn deploy -s ~/
这是从 Google+ 登录中使用的 GoogleApiClient 获取 token 的传统方式: String token = GoogleAuthUtil.getToken(apiClient.
我在阅读 facebook Open Graph 文档后比较确定我不能让网站“订阅”公共(public)页面,除非该页面安装了我的应用程序。如果那是错误的,请告诉我。 我想做的是一个照片库,非常简单,
我是一名优秀的程序员,十分优秀!