在API控制台中注册Android应用程序以进行Google API访问时,您必须输入您的应用程序SHA1证书指纹和应用程序的包名称。
现在我想知道,当api调用只是简单的HTTP请求时,Google如何验证这些值是正确的(在最简单的情况下,当你不使用他们的api客户端时,可能会附加一些头值)?在进行API调用时,必须提供API密钥,但这不能证明输入的值是正确的。
如果您没有使用Google Utils/SDK/API客户端,则必须手动传递这些标头。
如果您限制了android或ios应用程序的API密钥,则必须传递以下标头-
Android头文件:
{
'x-android-package': 'com.example',
'x-android-cert': '50FEC39F742F3DF212BDC2131A99C7D3C82086F6'
}
这里x-android-cert
标头的值是不带分号的签名密钥的SHA1指纹。
从密钥库文件中获取SHA1指纹-
keytools-list-v-keystore~/. android/debug.keystore-alias androiddebug key-store pass android-keypass android
要从签名的apk/bundle-获取SHA1指纹-
keytool-printcert-jarfile ~/下载/应用程序发布。aab
keytools-printcert-jarfile~/下载/app-release.apk
iOS标头:
{
'x-ios-bundle-identifier': 'com.example'
}
这里
com.example
是包标识符。
下面是Java中的类,我认为它在本地SDK中也做着同样的工作-
/**
* Intercepts requests and provides Android-specific headers so that API key restrictions can be
* enforced.
*/
public class AndroidAuthenticationInterceptor implements Interceptor {
...
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
...
final Request.Builder builder = chain.request().newBuilder();
if (config.packageName != null) {
builder.addHeader(HttpHeaders.X_ANDROID_PACKAGE, config.packageName);
}
if (config.certFingerprint != null) {
builder.addHeader(HttpHeaders.X_ANDROID_CERT, config.certFingerprint);
}
return chain.proceed(builder.build());
}
}
参考文献-
限制Google API的Android密钥的使用
- 如何找出用于签署应用程序的密钥库?
- https://developers.google.com/maps/api-security-best-practices
- https://github.com/googlemaps/google-maps-services-java/blob/9852dbae5d2c10897ad7a8dd4befcd171a2cd48e/src/main/java/com/google/maps/android/AndroidAuthenticationInterceptor.java
- https://github.com/googlemaps/google-maps-services-java/blob/main/src/main/java/com/google/maps/internal/HttpHeaders.java
您可以很容易地获得安装的应用程序的包名和sha 1指纹。
private void printSha1() {
List<ApplicationInfo> mAppList = getPackageManager().getInstalledApplications(0);
for (ApplicationInfo info :mAppList) {
Log.d(TAG, "Package Name: " + info.packageName);
Log.d(TAG, "Sha1: " + getCertificateSHA1Fingerprint(info.packageName));
}
}
private String getCertificateSHA1Fingerprint(String packageName) {
PackageManager pm = getPackageManager();
int flags = PackageManager.GET_SIGNATURES;
PackageInfo packageInfo = null;
try {
packageInfo = pm.getPackageInfo(packageName, flags);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Signature[] signatures = packageInfo.signatures;
byte[] cert = signatures[0].toByteArray();
InputStream input = new ByteArrayInputStream(cert);
CertificateFactory cf = null;
try {
cf = CertificateFactory.getInstance("X509");
} catch (CertificateException e) {
e.printStackTrace();
}
X509Certificate c = null;
try {
c = (X509Certificate) cf.generateCertificate(input);
} catch (CertificateException e) {
e.printStackTrace();
}
String hexString = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA1");
byte[] publicKey = md.digest(c.getEncoded());
hexString = byte2HexFormatted(publicKey);
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
} catch (CertificateEncodingException e) {
e.printStackTrace();
}
return hexString;
}
public static String byte2HexFormatted(byte[] arr) {
StringBuilder str = new StringBuilder(arr.length * 2);
for (int i = 0; i < arr.length; i++) {
String h = Integer.toHexString(arr[i]);
int l = h.length();
if (l == 1) h = "0" + h;
if (l > 2) h = h.substring(l - 2, l);
str.append(h.toUpperCase());
if (i < (arr.length - 1)) str.append(':');
}
return str.toString();
}
如果运行此代码,它将打印包名及其sha 1。这是您在创建API密钥时提供的两件事,因此谷歌根据它生成的密钥映射这两件事。
正如您所见,可以访问包名及其SHA 1打印,剩下的另一件事是API密钥,您可以通过代码或xml(清单,单独的xml配置文件)将其提供给必要的库或其他应用程序(Google Play服务)。
因此,每当Google为您提供任何东西时,它都可以检查您从API控制台生成密钥时生成的相关映射。
包名称的代码取自此处
问题内容: 我有一个字符串,一个签名和一个公共密钥,我想验证字符串上的签名。密钥如下所示: 我已经阅读了一段时间的pycrypto文档,但是我不知道如何使用这种密钥制作RSAobj。如果您了解PHP,我将尝试执行以下操作: 另外,如果我对任何术语感到困惑,请告诉我。 问题答案: 标记之间的数据是包含PKCS#1 RSAPublicKey的PKCS#8 PublicKeyInfo的ASN.1 DER
我们有一个java程序,它使用私钥对xml文件进行签名,如下所示: 现在,我必须验证这个签名在C使用cryptocpp。我所尝试的: 我验证了作为xmlString传递的数据与用于在java中创建签名的数据是二进制的。签名是base64编码的,我也尝试使用它进行解码。到目前为止,我总是失败。 如果我使用cryptopp创建带有私钥的签名,那么验证创建的签名就不会有问题。 这里可能有什么问题?我确信
我一直试图在一个我一直在做的网站上使用谷歌reCAPTCHA。验证码加载到网页上,但我无法使用几种方法验证它。我已经使用如何使用Python插件recaptcha客户端进行验证中给出的方法尝试了recaptcha验证?但我认为它已经过时了,因为它不再工作,它指的是挑战,而我试图使用的是谷歌新的“复选框”reCAPTCHA v2,或者我需要在安装recaptcha-client或django-rec
问题内容: 我有一个PHP脚本,应该检查“有效”人名,但是最近破解了一个带有空格的名称,因此我们在验证器中添加了空格。 除了这样做,还有没有办法向CakePHP的验证器添加黑名单以阻止所有“无效”字符,而不是允许“有效”字符? 注意:我知道如何在PHP中执行此操作(通常),但是使用CakePHP的验证器语法是不同的。 问题答案: 我同意其他意见,即验证名称可能不是一个好主意。 对于您可以想到的几乎
问题内容: 我知道该方法存在并且已记录,但是我不知道如何获取MapCanvasProjection对象。 问题答案: 在v2中更轻松-Google API v3的另一个缺陷!
我的项目正在对来自某些第三方软件的某些数据集进行签名验证。使用的签名算法是 。当我使用SDK附带的标准SUN加密提供程序时,一切都很顺利。最近我切换到了Bouncy Castle 1.50,之后,一些以前(即SUN提供者)进行验证的数据集开始失败,而其余的仍然被验证正常。 我探索了两个提供程序的源代码,结果发现SDK的默认提供程序对格式错误的签名有某种保护(同时能够恢复),而Bouncy Cast