限制YouTube API_KEY仅用于Android应用时遇403错误求助
YouTube API密钥限制Android应用后触发403错误的排查与解决
已执行操作
- 配置API密钥限制:在API密钥编辑页面选择「Android应用」,设置包名与调试指纹
- 包名与
AndroidManifest.xml完全一致:<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.xxxxxx.yyyyyy"> - 代码中指定应用名称:
public YouTube getYouTubeService() throws GeneralSecurityException, IOException { return new YouTube.Builder(GoogleNetHttpTransport.newTrustedTransport(), JSON_FACTORY, null) .setApplicationName("com.xxxxxx.yyyyyy") .build(); }
- 包名与
- 获取调试指纹:通过命令提取调试密钥库的SHA-1指纹
keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android - 验证指纹一致性:编写方法获取当前应用签名的SHA-1指纹,确认与API控制台配置一致
public String getSHA1Fingerprint() { try { PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES); for (Signature signature : info.signatures) { MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(signature.toByteArray()); byte[] digest = md.digest(); // 转换为带冒号的十六进制格式 StringBuilder hexString = new StringBuilder(); for (int i = 0; i < digest.length; i++) { if (i > 0) { hexString.append(":"); } String hex = Integer.toHexString(0xFF & digest[i]); if (hex.length() == 1) { hexString.append("0"); // 补前导零 } hexString.append(hex); } return hexString.toString().toUpperCase(); } } catch (Exception e) { e.printStackTrace(); } return null; }
问题现象
确认API控制台的包名、指纹与应用完全匹配,但设置限制后调用YouTube接口触发403错误,移除限制则正常调用。错误详情:
GET https://youtube.googleapis.com/youtube/v3/channels?id=xxxxxxxxxxxxx&key=yyyyyyyyyyyyyyyyyyyyyy&part=contentDetails { "code": 403, "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "API_KEY_ANDROID_APP_BLOCKED", "domain": "googleapis.com", "metadata": { "service": "youtube.googleapis.com", "consumer": "projects/1063253415806" } } ], "errors": [ { "domain": "global", "message": "Requests from this Android client application <empty> are blocked.", "reason": "forbidden" } ], "message": "Requests from this Android client application <empty> are blocked.", "status": "PERMISSION_DENIED" }
解决方案
错误信息中Android client application <empty>表明请求未携带应用的包名与签名验证信息——YouTube Data API的Java客户端库不会自动添加Android应用的验证头,需手动在请求中加入X-Android-Package和X-Android-Cert头:
修改后的代码
public YouTube getYouTubeService() throws GeneralSecurityException, IOException { String sha1Fingerprint = getSHA1Fingerprint(); String packageName = getPackageName(); return new YouTube.Builder(GoogleNetHttpTransport.newTrustedTransport(), JSON_FACTORY, new HttpRequestInitializer() { @Override public void initialize(HttpRequest request) throws IOException { // 添加Android验证头 request.getHeaders().set("X-Android-Package", packageName); request.getHeaders().set("X-Android-Cert", sha1Fingerprint.replace(":", "")); // 必须去掉指纹中的冒号 } }) .setApplicationName(packageName) .build(); }
关键注意事项
X-Android-Cert的值需为去掉冒号的SHA-1指纹,大小写与API控制台配置一致即可- 测试release包时,需在API控制台添加正式签名密钥库的SHA-1指纹
- 确保
getSHA1Fingerprint()获取的是当前运行应用的签名指纹(debug包用debug密钥库,release包用正式密钥库)
内容的提问来源于stack exchange,提问作者Fabio R Lopes
相关产品推荐
相关产品推荐

