You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Google API Java客户端库获取AccessToken时遇证书错误求助

我之前在项目里遇到过完全相同的JVM证书信任问题,给你几个经过实践验证的解决方案,按优先级试试:

解决方案1:确认证书导入的正确性(最常见的坑)

很多时候不是证书本身的问题,而是导入的路径或JDK版本错了:

  • 先确定当前应用使用的JDK路径:在代码里加一行System.out.println(System.getProperty("java.home")),运行后就能看到对应的JDK目录
  • 找到JDK的证书库位置:通常是{java.home}/lib/security/cacerts(Oracle JDK),OpenJDK部分版本是{java.home}/jre/lib/security/cacerts,别搞混了!
  • 用正确的keytool命令导入证书(默认密码是changeit):
    keytool -importcert -file /path/to/your/google-cert.pem -keystore /path/to/confirmed/cacerts -alias google-fcm-trust-cert
    
  • 导入时输入y确认,然后重启你的应用,确保应用加载的是修改后的证书库
解决方案2:在代码中自定义信任证书(推荐多JDK环境)

如果不想修改全局JVM证书,或者你的应用要在不同JDK环境运行,可以在代码里直接指定信任的证书,只影响当前应用:

import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import java.io.FileInputStream;
import java.io.File;
import java.io.InputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.KeyStore;
import java.security.TrustManagerFactory;
import java.security.SSLContext;
import java.security.SecureRandom;
import java.util.Arrays;

public static String getAccessToken() throws Exception {
    // 1. 加载你下载的Google根证书(比如从浏览器导出的.pem文件)
    CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
    File certFile = new File("/path/to/google-root-cert.pem");
    InputStream certIn = new FileInputStream(certFile);
    X509Certificate googleCert = (X509Certificate) certFactory.generateCertificate(certIn);
    certIn.close();

    // 2. 创建自定义信任库并添加证书
    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    trustStore.load(null, null);
    trustStore.setCertificateEntry("google-fcm-cert", googleCert);

    // 3. 构建自定义TrustManager和SSLContext
    TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmFactory.init(trustStore);
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmFactory.getTrustManagers(), new SecureRandom());

    // 4. 配置带自定义SSL的HttpTransport
    HttpTransport customHttpTransport = new NetHttpTransport.Builder()
            .setSslSocketFactory(sslContext.getSocketFactory())
            .build();

    // 5. 用自定义Transport构建GoogleCredential
    GoogleCredential googleCredential = GoogleCredential
            .fromStream(new FileInputStream(PATH_JSON_AUTH02), customHttpTransport, new JacksonFactory())
            .createScoped(Arrays.asList(URL_SCOPE_FCM));
    googleCredential.refreshToken();
    return googleCredential.getAccessToken();
}
解决方案3:排查企业代理证书问题

如果你的应用是在企业内网环境,通过代理上网,那问题大概率是代理替换了SSL证书,这时候你需要导入代理的根证书,而不是Google的证书:

  • 用浏览器访问https://oauth2.googleapis.com/token,查看证书详情(不同浏览器操作略有不同),找到代理的根证书并导出
  • 按照解决方案1的步骤,把代理根证书导入到JVM的cacerts中
解决方案4:临时禁用证书验证(仅用于测试!)

这个方法非常不安全,绝对不能用于生产环境,只能用来快速确认是否是证书信任问题导致的错误:

import javax.net.ssl.*;
import java.security.cert.X509Certificate;

// 在调用getAccessToken()之前执行这段代码(仅测试用)
static {
    try {
        TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() { return null; }
                public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                public void checkServerTrusted(X509Certificate[] certs, String authType) {}
            }
        };
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

内容的提问来源于stack exchange,提问作者Bruno Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:20:34