java.lang.NoClassDefFoundError:com / google / appengine / api / urlfetch / HTTPMethod

时间:2018-12-29 17:58:45

标签: java google-app-engine google-api google-api-client urlfetch

我尝试按照以下方式通过后端服务器验证Google ID令牌:

https://developers.google.com/identity/sign-in/android/backend-auth

这些令牌最初是由android应用检索的,然后通过尝试验证的套接字传递给后端登录服务器。就目前情况而言,我正在导入的GoogleIdTokenVerifier代码在运行时抛出错误。

ServerThread.java:

GoogleIdToken idToken = GoogleAuthenticator.authenticateToken(tokenJson.getToken());

GoogleAuthenticator.java:

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.Properties;

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.extensions.appengine.http.UrlFetchTransport;

public class GoogleAuthenticator {

    public GoogleAuthenticator(){

    }

    public static Properties prop;

    public static GoogleIdToken authenticateToken(String inputToken) throws IOException{

    final JacksonFactory jacksonFactory = new JacksonFactory();
    prop = new Properties();
    prop.load(GoogleAuthenticator.class.getClassLoader().getResourceAsStream("config.properties"));

    GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(UrlFetchTransport.getDefaultInstance(), jacksonFactory)
            // Specify the CLIENT_ID of the app that accesses the backend:
            .setAudience(Collections.singletonList(prop.getProperty("google.web.client.id")))
            // Or, if multiple clients access the backend:
            //.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
            .build();

        GoogleIdToken idToken;
        try {
            idToken = verifier.verify(inputToken);
            return idToken;
        } catch (GeneralSecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }
}

pom.xml

    <dependency>
        <groupId>com.google.api-client</groupId>
        <artifactId>google-api-client</artifactId>
        <version>1.25.0</version>
   </dependency>

   <dependency>
        <groupId>com.google.api-client</groupId>
        <artifactId>google-api-client-appengine</artifactId>
        <version>1.25.0</version>
   </dependency>

我目前看到以下堆栈跟踪:

Exception in thread "Thread-0" java.lang.NoClassDefFoundError: com/google/appengine/api/urlfetch/HTTPMethod
    at com.google.api.client.extensions.appengine.http.UrlFetchTransport.buildRequest(UrlFetchTransport.java:118)
    at com.google.api.client.extensions.appengine.http.UrlFetchTransport.buildRequest(UrlFetchTransport.java:50)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:872)
    at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.refresh(GooglePublicKeysManager.java:172)
    at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.getPublicKeys(GooglePublicKeysManager.java:140)
    at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:174)
    at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:192)
    at com.omarhegazi.login.GoogleAuthenticator.authenticateToken(GoogleAuthenticator.java:40)
    at com.omarhegazi.login.ServerThread.run(ServerThread.java:45)

在依赖关系中似乎没有可用的HTTPMethod类。有什么想法吗?

更新1:

在下面添加appengine依赖项已经取得了一些进展。我现在有以下堆栈跟踪错误:

Exception in thread "Thread-0" com.google.apphosting.api.ApiProxy$CallNotFoundException: The API package 'urlfetch' or call 'Fetch()' was not found.
    at com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:98)
    at com.google.appengine.api.urlfetch.URLFetchServiceImpl.fetch(URLFetchServiceImpl.java:37)
    at com.google.api.client.extensions.appengine.http.UrlFetchRequest.execute(UrlFetchRequest.java:74)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:981)
    at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.refresh(GooglePublicKeysManager.java:172)
    at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.getPublicKeys(GooglePublicKeysManager.java:140)
    at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:174)
    at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:192)
    at com.omarhegazi.login.GoogleAuthenticator.authenticateToken(GoogleAuthenticator.java:40)
    at com.omarhegazi.login.ServerThread.run(ServerThread.java:45)

这是使用v1.6.1

我还尝试使用v1.9.70,结果如下:

Exception in thread "Thread-0" com.google.apphosting.api.ApiProxy$CallNotFoundException: Can't make API call urlfetch.Fetch in a thread that is neither the original request thread nor a thread created by ThreadManager
    at com.google.apphosting.api.ApiProxy$CallNotFoundException.foreignThread(ApiProxy.java:800)
    at com.google.apphosting.api.ApiProxy.makeSyncCall(ApiProxy.java:112)
    at com.google.appengine.api.urlfetch.URLFetchServiceImpl.fetch(URLFetchServiceImpl.java:40)
    at com.google.api.client.extensions.appengine.http.UrlFetchRequest.execute(UrlFetchRequest.java:74)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:981)
    at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.refresh(GooglePublicKeysManager.java:172)
    at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.getPublicKeys(GooglePublicKeysManager.java:140)
    at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:174)
    at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:192)
    at com.omarhegazi.login.GoogleAuthenticator.authenticateToken(GoogleAuthenticator.java:40)
    at com.omarhegazi.login.ServerThread.run(ServerThread.java:45)

貌似fetch软件包在1.6.1以后才包含,但存在一些与API调用线程有关的问题。

2 个答案:

答案 0 :(得分:1)

尝试在您的appengine中包含pom.xml依赖项:

<dependency>
    <groupId>com.google.appengine</groupId>
    <artifactId>appengine-api-1.0-sdk</artifactId>
    <version>1.6.1</version> <!-- Check your version --> 
</dependency>

Link to the docs

答案 1 :(得分:0)

根据上面ngueno的帖子,我需要appengine-api-1.0-sdk v1.9.70才能使其正常工作:

 <dependency>
    <groupId>com.google.appengine</groupId>
    <artifactId>appengine-api-1.0-sdk</artifactId>
    <version>1.9.70</version>
</dependency>

解决“无法在原始请求线程也不是由ThreadManager创建的线程的线程中进行API调用urlfetch.Fetch” 错误,此版本的appengine API,我必须将使用的HTTPTransport从 UrlFetchTransport.getDefaultInstance()更改为 GoogleNetHttpTransport.newTrustedTransport()

即:

    HtpTransport httpTransport = GoogleNetHtpTransport.newTrustedTransport();
    prop = new Properties();
prop.load(GoogleAuthenticator.class.getClassLoader().getResourceAsStream("config.properties"));

    GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(httpTransport, gsonFactory)
            // Specify the CLIENT_ID of the app that accesses the backend:
            .setAudience(Collections.singletonList(prop.getProperty("google.client.id")))
            .setIssuer("https://accounts.google.com")
            // Or, if multiple clients access the backend:
            //.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
            .build();

        // (Receive idTokenString by HTTPS POST)

        GoogleIdToken idToken;

        idToken = verifier.verify(inputToken);

所使用的所有参考和指南都指出UrlFetchTransport.getDefaultInstance()是线程安全的/最佳的选择,但在这里对我不起作用。