java,驱动APIv2,appengine 1.7.3,struts2.3.4.1,OAuth2。 TokenResponseException:400 OK invalid_grant

我收到错误invalid_grant我已经看过googleing arround,但是在这个问题已经有几天了。 错误被抛入:

File file = insert.execute(); 

我只是想从我的webapp上传文件到google驱动器。 我正在使用服务帐户在API Access(https://code.google.com/apis/console/)中生成的私钥对(.p12):

  Service account Use service accounts to call Google APIs on behalf of your application instead of an end-user. Learn more Client ID: xxx-xxxxxx.apps.googleusercontent.com Email address: xxx-xxxxxxxxxxx@developer.gserviceaccount.com Public key fingerprints: a108d8713103e09d0013655c9f80458f03e3a38a – Delete... 

在Google APis – >驱动SDK(https://code.google.com/apis/console/?api=drive#project:347347146680:drive_sdk)中,我已将此ClientID放入:

 Drive Integration OAuth Client ID (Required) Enter the Client ID for your application. You can configure a client ID on the "API Access" panel. 

任何帮助将是欣赏! 谢谢!

我的代码:

struts.xml中:

        jsp/common/upload.jsp   jsp/common/upload.jsp   image/jpeg,image/gif,image/png photoStream filename="photo.jpg" 1024   

Upload.java:

 //File uploading (see struts.xml interceptors & struts2-gae-0.1.jar private String photo; private String photoContentType; //The content type of the file private String photoFileName; //The uploaded file name private InputStream photoStream; [...] public String upload() { try { if (photo!=null) { GoogleDrive.insertLocalFile("title","description",null,photoContentType,photo); } } catch (Exception e ) { log.debug(new String(), e); } return SUCCESS2; } 

GoogleDrive.java:

 public static File insertLocalFile(String title, String description, String parentId, String mimeType, String data) { File body = new File(); body.setTitle(title); body.setDescription(description); body.setMimeType(mimeType); Drive service = null; try { service = getDriveService(); Files files = service.files(); InputStreamContent isc = new InputStreamContent(mimeType); isc.setData(data); Insert insert = files.insert(body, isc); //mediaContent); File file = insert.execute(); return file; } catch (IOException e) { log.error(new String(), e); return null; } } public static Drive getDriveService() { HttpTransport httpTransport = new NetHttpTransport(); JacksonFactory jsonFactory = new JacksonFactory(); GoogleCredential credential; Drive service = null; try { credential = new GoogleCredential.Builder() .setTransport(httpTransport) .setJsonFactory(jsonFactory) //.setServiceAccountId(SERVICE_ACCOUNT_EMAIL) .setServiceAccountId(SERVICE_ACCOUNT_ID) .setServiceAccountScopes(DriveScopes.DRIVE_FILE) .setServiceAccountPrivateKeyFromP12File(new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH)) .setServiceAccountUser(SERVICE_ACCOUNT_EMAIL) .build(); service = new Drive.Builder(httpTransport, jsonFactory, null) .setHttpRequestInitializer(credential).build(); } catch (GeneralSecurityException e) { log.error(new String(), e); } catch (IOException e) { log.error(new String(), e); } return service; } 

堆栈跟踪:

 com.google.api.client.auth.oauth2.TokenResponseException: 400 OK { "error" : "invalid_grant" } at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:103) at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:303) at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:323) at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:340) at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:505) at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:266) at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:857) at com.google.api.client.googleapis.media.MediaHttpUploader.executeUploadInitiation(MediaHttpUploader.java:337) at com.google.api.client.googleapis.media.MediaHttpUploader.upload(MediaHttpUploader.java:252) at com.google.api.services.drive.Drive$Files$Insert.executeUnparsed(Drive.java:309) at com.google.api.services.drive.Drive$Files$Insert.execute(Drive.java:331) at util.google.GoogleDrive.insertLocalFile(GoogleDrive.java:365) at com.lm.action.common.Upload.upload(Upload.java:108) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:115) at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:453) at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:292) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:255) at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:236) at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:236) at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:90) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171) at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) at com.struts2.gae.interceptor.GaeFileUploadInterceptor.intercept(GaeFileUploadInterceptor.java:275) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249) at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54) at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:511) at org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:432) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:123) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:61) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:94) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:383) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.Server.handle(Server.java:326) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755) at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) 

您错误地使用了服务帐户ID。 你应该使用:

 credential = new GoogleCredential.Builder() .setTransport(httpTransport) .setJsonFactory(jsonFactory) .setServiceAccountId(SERVICE_ACCOUNT_EMAIL) //.setServiceAccountId(SERVICE_ACCOUNT_ID) .setServiceAccountScopes(DriveScopes.DRIVE_FILE) .setServiceAccountPrivateKeyFromP12File(new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH)) //.setServiceAccountUser(SERVICE_ACCOUNT_EMAIL) .build(); 

仅当您要模拟真实用户时,才应使用setServiceAccountUser()方法。