2017-10-12 23 views
12

我成功创建,以对谷歌张写弹簧引导服务类,继后未经授权的Java Quistart Tutorial for Sheets API谷歌表Java SDK的OAuth的几个小时(春季启动)

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

下面的代码,在此先感谢

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(); 
+0

我认为https://www.draw.io的人可能有同样的问题 –

+0

我使用了错误的进场?我试图检查如何处理Api-Key,但我没有找到任何示例 – user4330585

+0

我不知道答案。我会开始在这个问题上的赏金,以获得更多的关注可能知道它的其他人 –

回答

2

有一个名为刷新令牌,它的概念看起来适合您的需求。

你可以找到在这个问题提得好discribe: https://stackoverflow.com/a/7209263/4988996

编辑:根据您的意见,我发现谷歌已经使用Credential DataStoreCredentialRefreshListener

访问受保护的资源。如果适用,已过期的访问令牌将使用刷新令牌自动刷新。确保使用DataStoreCredentialRefreshListener并使用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)); }

+1

感谢您的回复,你知道是否有任何示例准备与谷歌床单的Java SDK? – user4330585

+0

根据您的评论编辑答案。看一看。 –

+0

@ user4330585您是否尝试过这种解决方案?任何反馈?今天的赏金到期 –