Android应用安全验证:Play Integrity API集成与测试工具开发实战

1. 项目概述:为什么我们需要一个Play Integrity Checker?

如果你是一名Android开发者,或者对Android设备安全、应用生态的“纯净度”感兴趣,那么“Play Integrity API”这个词你肯定不陌生。简单来说,它是Google Play服务提供的一套API,用于验证运行你应用的设备是否真实、未被篡改,以及应用本身是否来自可信渠道。这听起来像是Google在“管闲事”,但实际上,它关乎应用开发者的核心利益和用户的最终体验。

想象一下,你开发了一款付费应用或包含内购的游戏。如果用户通过修改系统、使用非官方渠道安装的修改版APK,或者运行在模拟器上,轻松绕过了你的付费验证,你的收入从何而来?更进一步,如果一些恶意软件或自动化脚本在大量虚拟设备上运行你的应用,进行刷榜、刷评论或欺诈活动,不仅损害你的经济利益,还会污染你的应用数据,让基于用户行为的算法推荐完全失效。Play Integrity API就是为了应对这些挑战而生的“守门员”。

然而,作为开发者,我们如何知道自己的应用集成是否正确?如何测试不同设备(包括那些可能被Root或安装了Magisk的设备)的验证结果?如何向测试团队或合作伙伴直观地展示验证状态?这就是“Play Integrity Checker”工具的价值所在。它不是一个简单的API调用演示,而是一个功能完整、可独立运行、能深入展示验证细节的Android应用。通过构建这样一个工具,你不仅能彻底掌握Play Integrity API的集成与调试方法,更能将其核心验证逻辑可视化,成为一个在日常开发和测试中极具实用价值的“瑞士军刀”。

2. 核心原理与API深度解析

在动手敲代码之前,我们必须吃透Play Integrity API的工作原理。它远不止一个返回“真”或“假”的简单接口。

2.1 Play Integrity API的三层验证体系

Play Integrity API的验证结果不是一个布尔值,而是一个包含多个字段的令牌(Token),解码后主要包含三个核心部分的评估:

  1. 设备完整性(Device Integrity) :评估设备本身的状态。理想情况下,设备应通过Android兼容性测试套件(CTS),并且系统未被篡改。这里会返回如 MEETS_DEVICE_INTEGRITY 这样的结果。如果设备被Root、Bootloader已解锁或安装了自定义ROM,这部分验证就可能失败。

  2. 应用完整性(App Integrity) :验证应用本身的安装来源和完整性。关键结果是 MEETS_BASIC_INTEGRITY MEETS_STRONG_INTEGRITY

    • MEETS_BASIC_INTEGRITY :意味着应用运行在一个基本的、未被深度篡改的Android环境上。即使设备被Root,只要应用包名、签名证书与Google Play上记录的一致,通常仍能通过基础完整性检查。这是防止在模拟器或严重篡改系统上运行的最低防线。
    • MEETS_STRONG_INTEGRITY :这是最高级别的应用完整性。它要求应用必须是从Google Play商店安装的,且未被重新打包或修改。任何来自第三方商店、通过ADB侧载或修改过的APK,都无法满足强完整性。
  3. 账户详情(Account Details) :可选部分,用于验证用户账户是否正常(例如,不是被开发者列入黑名单的账户)。这对于打击滥用行为的进阶策略很有用。

注意 MEETS_DEVICE_INTEGRITY MEETS_STRONG_INTEGRITY 是两个不同维度的概念。一个从官方Play商店安装的应用在已Root的设备上,可能满足 MEETS_STRONG_INTEGRITY (因为应用来源纯净),但无法满足 MEETS_DEVICE_INTEGRITY (因为设备系统被修改)。

2.2 集成流程与密钥管理

集成Play Integrity API的核心步骤包括服务端和客户端的配合:

  1. 在Google Play Console中配置 :这是起点。你需要为你的应用在Play Console中启用Play Integrity API。更重要的是,你需要在这里创建一个“非对称密钥对”。Google会保存公钥,而私钥(一个 .json 文件)则由你下载并妥善保管在 你的应用后端服务器 上。这个私钥 绝对不应该 被打包到客户端APK中,否则会被轻易提取,导致验证形同虚设。

  2. 客户端(Android App)发起请求 :在你的应用(也就是我们要构建的Checker工具)中,调用Integrity API,你会得到一个加密的 integrityToken 。这个令牌本身对你(客户端)是不可读的。

  3. 服务端验证令牌 :客户端将这个 integrityToken 发送到你自己的后端服务器。服务器使用之前下载的私钥,调用Google的验证接口( https://playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken )来解密和验证这个令牌。验证结果会以清晰的JSON格式返回,包含了上述所有的完整性评估细节、时间戳、设备信息等。

  4. 服务端将结果返回客户端 :你的服务器将验证后的、可读的结果返回给Android客户端,客户端再根据结果决定后续流程(如允许登录、禁止交易等)。

对于我们这个“Play Integrity Checker”工具,为了使其能独立运行而不依赖一个复杂的后端,我们将采用一种简化但安全的模式:我们依然遵循客户端-服务端架构,但我们可以构建一个极简的、仅供演示和测试用的后端(例如,使用Cloud Functions、Firebase或一个简单的Python Flask服务),并将这个后端的地址硬编码或配置在App中。 关键在于,这个演示后端的私钥仅用于此测试工具,且你需要明白在生产环境中,私钥必须由你真正的业务服务器保管。

3. 开发环境搭建与项目初始化

工欲善其事,必先利其器。我们选择Android Studio作为开发环境,它是Google官方的IDE,对Play Integrity API等Google服务有最好的支持。

3.1 Android Studio配置要点

如果你已经安装了Android Studio,请确保SDK工具更新至最新。特别是 Google Play services Google Repository 这两个SDK组件必须安装。你可以在Android Studio的 Settings/Preferences -> Appearance & Behavior -> System Settings -> Android SDK -> SDK Tools 选项卡中检查和安装。

对于网络搜索热词中提到的“android studio怎么设置中文?”,这属于IDE界面语言设置,并不影响编码。你可以在 Settings/Preferences -> Plugins -> Marketplace 中搜索“Chinese (Simplified) Language Pack”插件并安装,重启后即可切换为中文界面。但考虑到开发文档和社区资源多以英文为主,我个人建议保持英文界面,这对长期学习和排查问题更有帮助。

3.2 创建新项目与依赖配置

  1. 新建项目 :打开Android Studio,选择“New Project”,模板选择“Empty Views Activity”(即传统的基于View的Activity,为了更清晰地展示逻辑,我们暂不使用Compose)。项目命名如 PlayIntegrityChecker ,包名可设为 com.yourname.playintegritychecker ,语言选择Kotlin(推荐,代码更简洁),最低API级别建议设为API 24(Android 7.0),以覆盖大多数设备。

  2. 添加关键依赖 :打开项目根目录的 build.gradle.kts (Module: app) 文件,在 dependencies 块中添加以下依赖:

    dependencies {
        implementation("com.google.android.play:integrity:1.3.0") // Play Integrity API 客户端库
        implementation("com.squareup.retrofit2:retrofit:2.9.0") // 用于网络请求到我们的验证服务器
        implementation("com.squareup.retrofit2:converter-gson:2.9.0") // 用Gson解析JSON
        implementation("com.google.code.gson:gson:2.10.1") // Gson库
        // 其他基础依赖...
    }
    

    添加后同步(Sync)项目。

  3. 配置网络权限 :由于应用需要向你的验证服务器发送请求,必须在 AndroidManifest.xml 文件中添加互联网权限:

    <uses-permission android:name="android.permission.INTERNET" />
    

3.3 模拟验证服务器的准备(关键步骤)

为了让工具能独立运行,我们需要一个临时性的“验证服务器”。这里提供两个最快捷的方案:

方案A:使用Google Cloud Functions(无服务器,推荐) 这是最接近生产环境的简易方案。你可以编写一个Node.js或Python函数,接收令牌,调用Google验证接口,然后返回结果。

  1. 在Google Cloud Platform创建一个新项目。
  2. 启用Cloud Functions API。
  3. 编写一个HTTP触发的函数,核心逻辑是使用你从Play Console下载的私钥文件,初始化Google API客户端,然后解码令牌。
  4. 部署函数后,你会得到一个HTTPS端点(例如 https://your-region-your-project.cloudfunctions.net/verifyToken )。将这个URL配置到你的Android应用中。

方案B:使用本地测试服务器(如Python Flask,仅用于开发) 对于纯本地测试,你可以快速搭建一个Flask服务器。

# 示例:app.py (务必不要在生产环境使用此简单代码)
from flask import Flask, request, jsonify
from google.oauth2 import service_account
from googleapiclient.discovery import build
import json

app = Flask(__name__)

# 加载从Play Console下载的私钥JSON文件
SERVICE_ACCOUNT_KEY_FILE = 'your-private-key.json'
credentials = service_account.Credentials.from_service_account_file(
    SERVICE_ACCOUNT_KEY_FILE,
    scopes=['https://www.googleapis.com/auth/playintegrity']
)
service = build('playintegrity', 'v1', credentials=credentials)

@app.route('/verify', methods=['POST'])
def verify_token():
    data = request.json
    integrity_token = data.get('token')
    package_name = 'com.yourname.playintegritychecker' # 你的应用包名

    request_body = {'integrityToken': integrity_token}
    response = service.decodeIntegrityToken(packageName=package_name, body=request_body).execute()
    return jsonify(response)

if __name__ == '__main__':
    app.run(ssl_context='adhoc', host='0.0.0.0', port=5000) # 注意:需要HTTPS

在电脑上运行此脚本,并确保手机和电脑在同一局域网。你需要将Android应用中的服务器地址设为 https://你的电脑IP:5000/verify 重要:Android Pie (API 28) 及以上默认要求HTTPS,所以本地测试也需要配置SSL(如上例使用 adhoc )或修改App的网络安全配置。

实操心得 :在开发初期,强烈建议使用方案B进行快速迭代和调试。你可以先在电脑上运行Flask服务器,用Postman测试通接口,再集成到App中。这能帮你隔离客户端和服务端问题。记得在 AndroidManifest.xml <application> 标签内添加 android:usesCleartextTraffic="true" 以允许HTTP通信(仅限调试!),或者为调试构建配置网络安全配置文件以信任你的自签名证书。

4. 客户端应用核心功能实现

现在,我们开始构建Checker工具的Android客户端部分。核心界面可以很简单:一个按钮用于触发检查,几个TextView用于显示结果。

4.1 用户界面设计

打开 activity_main.xml ,设计一个简单的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <Button
        android:id="@+id/btn_check"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="32dp"
        android:text="开始完整性检查" />

    <TextView
        android:id="@+id/tv_status"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:text="状态:等待检查..."
        android:textSize="16sp" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:layout_marginTop="16dp">

        <TextView
            android:id="@+id/tv_result"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#f5f5f5"
            android:padding="12dp"
            android:text="详细结果将显示在这里..."
            android:textIsSelectable="true" /> <!-- textIsSelectable允许用户复制文本 -->
    </ScrollView>

</LinearLayout>

这个布局包含一个触发按钮、一个状态提示框和一个可滚动、可复制的文本框用于显示详细的JSON结果。

4.2 集成Play Integrity API客户端

MainActivity.kt 中,我们实现核心逻辑。

首先,初始化Play Integrity Manager:

import com.google.android.play.core.integrity.IntegrityManager
import com.google.android.play.core.integrity.IntegrityManagerFactory
import com.google.android.play.core.integrity.IntegrityTokenRequest
import com.google.android.play.core.integrity.IntegrityTokenResponse
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability

class MainActivity : AppCompatActivity() {
    private lateinit var integrityManager: IntegrityManager
    private lateinit var btnCheck: Button
    private lateinit var tvStatus: TextView
    private lateinit var tvResult: TextView

    // 你的后端验证服务器地址(请替换为实际地址)
    private val YOUR_SERVER_URL = "https://your-server.com/verify"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btnCheck = findViewById(R.id.btn_check)
        tvStatus = findViewById(R.id.tv_status)
        tvResult = findViewById(R.id.tv_result)

        // 1. 检查Google Play服务是否可用
        if (!isGooglePlayServicesAvailable()) {
            tvStatus.text = "状态:错误 - 设备未安装或版本过旧的Google Play服务"
            btnCheck.isEnabled = false
            return
        }

        // 2. 创建IntegrityManager实例
        integrityManager = IntegrityManagerFactory.create(applicationContext)

        btnCheck.setOnClickListener {
            requestIntegrityToken()
        }
    }

    private fun isGooglePlayServicesAvailable(): Boolean {
        val googleApiAvailability = GoogleApiAvailability.getInstance()
        val resultCode = googleApiAvailability.isGooglePlayServicesAvailable(this)
        return resultCode == ConnectionResult.SUCCESS
    }
    // ... 后续代码
}

4.3 请求令牌与处理服务器验证

接着,实现 requestIntegrityToken 方法,向Play服务请求令牌,然后发送到我们的服务器进行验证。

private fun requestIntegrityToken() {
    tvStatus.text = "状态:正在请求完整性令牌..."
    tvResult.text = ""
    btnCheck.isEnabled = false

    // 构建令牌请求
    val integrityTokenRequest = IntegrityTokenRequest.builder()
        .setNonce(generateNonce()) // 生成一个随机数防止重放攻击
        .setCloudProjectNumber(YOUR_CLOUD_PROJECT_NUMBER) // 你在Google Cloud的项目编号
        .build()

    integrityManager.requestIntegrityToken(integrityTokenRequest)
        .addOnSuccessListener { response: IntegrityTokenResponse ->
            val integrityToken = response.token()
            tvStatus.text = "状态:令牌获取成功,正在验证..."
            // 将令牌发送到你的服务器进行验证
            sendTokenToServer(integrityToken)
        }
        .addOnFailureListener { e ->
            runOnUiThread {
                tvStatus.text = "状态:请求令牌失败 - ${e.localizedMessage}"
                btnCheck.isEnabled = true
                tvResult.text = "错误详情:\n${e.stackTraceToString()}"
            }
        }
}

private fun generateNonce(): String {
    // 生成一个随机的Base64编码的字符串作为Nonce
    val random = SecureRandom()
    val bytes = ByteArray(16) // 16字节足够
    random.nextBytes(bytes)
    return Base64.encodeToString(bytes, Base64.URL_SAFE or Base64.NO_WRAP)
}

private fun sendTokenToServer(token: String) {
    // 使用Retrofit进行网络请求
    val retrofit = Retrofit.Builder()
        .baseUrl(YOUR_SERVER_URL) // 注意:这里应该是基础URL,如 https://your-server.com/
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val service = retrofit.create(VerificationService::class.java)
    val call = service.verifyToken(VerificationRequest(token))

    call.enqueue(object : Callback<VerificationResponse> {
        override fun onResponse(call: Call<VerificationResponse>, response: Response<VerificationResponse>) {
            runOnUiThread {
                btnCheck.isEnabled = true
                if (response.isSuccessful) {
                    val result = response.body()
                    tvStatus.text = "状态:服务器验证成功!"
                    // 格式化并显示详细的JSON结果
                    val gson = GsonBuilder().setPrettyPrinting().create()
                    val prettyJson = gson.toJson(result)
                    tvResult.text = prettyJson
                    // 可以在这里添加逻辑,解析result中的deviceIntegrity, appIntegrity等字段,给出更友好的提示
                    parseAndDisplaySummary(result)
                } else {
                    tvStatus.text = "状态:服务器返回错误 - ${response.code()}"
                    tvResult.text = "错误响应体:\n${response.errorBody()?.string()}"
                }
            }
        }

        override fun onFailure(call: Call<VerificationResponse>, t: Throwable) {
            runOnUiThread {
                tvStatus.text = "状态:网络请求失败"
                tvResult.text = "异常信息:\n${t.localizedMessage}"
                btnCheck.isEnabled = true
            }
        }
    })
}

// 定义网络请求接口
interface VerificationService {
    @POST("verify") // 与你的服务器端点对应
    fun verifyToken(@Body request: VerificationRequest): Call<VerificationResponse>
}

// 请求体和响应体的数据类
data class VerificationRequest(val token: String)
data class VerificationResponse(
    // 根据Google API返回的实际JSON结构定义字段
    val requestDetails: RequestDetails?,
    val appIntegrity: AppIntegrity?,
    val deviceIntegrity: DeviceIntegrity?,
    val accountDetails: AccountDetails?
    // ... 其他字段
) {
    data class RequestDetails(val requestPackageName: String?, val timestampMillis: Long?)
    data class AppIntegrity(val appRecognitionVerdict: String?, val packageName: String?, val certificateSha256Digest: List<String>?)
    data class DeviceIntegrity(val deviceRecognitionVerdict: List<String>?)
    data class AccountDetails(val appLicensingVerdict: String?)
}

// 解析并显示摘要信息
private fun parseAndDisplaySummary(response: VerificationResponse?) {
    response?.let {
        val summary = StringBuilder()
        summary.append("=== 完整性检查摘要 ===\n\n")

        // 设备完整性
        val deviceVerdicts = it.deviceIntegrity?.deviceRecognitionVerdict
        if (deviceVerdicts.isNullOrEmpty()) {
            summary.append("设备完整性: 未通过\n")
        } else {
            summary.append("设备完整性: ${deviceVerdicts.joinToString(", ")}\n")
            // 判断常见状态
            when {
                deviceVerdicts.contains("MEETS_DEVICE_INTEGRITY") -> summary.append("   → 设备状态良好,系统可信。\n")
                else -> summary.append("   → 设备可能被修改(如Root、解锁Bootloader)。\n")
            }
        }

        // 应用完整性
        val appVerdict = it.appIntegrity?.appRecognitionVerdict
        summary.append("\n应用完整性: ${appVerdict ?: "未知"}\n")
        when (appVerdict) {
            "MEETS_STRONG_INTEGRITY" -> summary.append("   → 应用来自Google Play商店,且未被篡改。\n")
            "MEETS_BASIC_INTEGRITY" -> summary.append("   → 应用运行在基本完整的环境,但可能非官方渠道安装。\n")
            null, "UNKNOWN" -> summary.append("   → 无法确定应用完整性。\n")
            else -> summary.append("   → 应用完整性验证失败。\n")
        }

        // 在详细JSON结果前插入摘要
        val currentText = tvResult.text.toString()
        tvResult.text = "$summary\n--- 原始JSON详情 ---\n$currentText"
    }
}

5. 测试、验证与结果解读

构建好应用后,最关键的环节就是测试。你需要在不同状态的设备上安装并运行你的Checker工具,观察结果。

5.1 构建与安装测试包

  1. 在Android Studio中,生成一个签名后的APK(或使用调试密钥签名的APK用于测试)。 重要 :你必须在Google Play Console中,将你用于签名的证书指纹(SHA-1或SHA-256)添加到你的应用的“Play Integrity API”配置下的“允许的证书”列表中。否则,验证会失败。
  2. 将APK安装到测试设备上。准备以下几类测试设备:
    • 纯净官方设备 :未Root、未解锁Bootloader、从Play商店安装你的Checker。
    • Root设备 :已获取Root权限(如通过Magisk)的设备。
    • 模拟器 :Android Studio自带的模拟器。
    • 侧载安装 :通过ADB命令 adb install app-debug.apk 安装,模拟非Play商店渠道。

5.2 运行测试与结果分析

在每类设备上运行应用,点击检查按钮。观察状态和详细结果。

  • 在纯净官方设备上 :预期结果应包含 deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"] appRecognitionVerdict: "MEETS_STRONG_INTEGRITY" 。这是最理想的状态。
  • 在Root设备上 deviceRecognitionVerdict 很可能为空或不包含 MEETS_DEVICE_INTEGRITY 。但 appRecognitionVerdict 可能仍是 MEETS_STRONG_INTEGRITY (如果App是从Play商店安装的)。这直观展示了设备完整性和应用完整性的区别。
  • 在模拟器上 :通常两者都无法通过, appRecognitionVerdict 可能是 MEETS_BASIC_INTEGRITY 或更低。
  • 通过ADB侧载安装 appRecognitionVerdict 将不会是 MEETS_STRONG_INTEGRITY ,因为它不是来自Play商店。

5.3 常见问题排查实录

在开发和测试过程中,你几乎一定会遇到下面这些问题:

问题1:调用 requestIntegrityToken 直接失败,返回错误码 -11 (API_NOT_AVAILABLE)。

  • 原因 :最常见的原因是设备上没有安装或未更新Google Play服务。或者,你使用的Cloud Project Number不属于一个已正确启用并配置了Play Integrity API的Google Cloud项目。
  • 排查
    1. 确保测试设备上Google Play服务已更新至最新。
    2. 在Play Console中,确认你的应用(包名)已启用Play Integrity API。
    3. 确认代码中的 YOUR_CLOUD_PROJECT_NUMBER 填写正确。这个数字是Google Cloud项目编号,不是Play Console的应用ID。你可以在Google Cloud Console项目概览页找到它。

问题2:服务器验证返回HTTP 403错误。

  • 原因 :服务器端调用Google API时认证失败。
  • 排查
    1. 确保服务器代码中加载的私钥JSON文件是正确的,且来自Play Console中对应应用的配置。
    2. 确保服务器代码中请求的 packageName 参数与私钥所属的应用包名完全一致。
    3. 检查Google Cloud服务账号是否有权限访问Play Integrity API。你需要在Google Cloud Console为你的服务账号分配“Play Integrity API User”角色。

问题3:验证结果中 appRecognitionVerdict 始终不是 MEETS_STRONG_INTEGRITY ,即使是从Play商店安装的。

  • 原因 :你可能使用了调试签名(debug keystore)构建APK进行测试,但未在Play Console中注册调试证书指纹。
  • 排查
    1. 获取你的调试密钥的SHA-256指纹:
      keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
      
    2. 将得到的SHA-256指纹值,添加到Play Console中你的应用下的 Play Integrity API -> 允许的证书 列表中。
    3. 重新构建安装测试。注意,这个配置可能需要几个小时才能在全球生效。

问题4:网络搜索热词中提到的路径,如 /storage/emulated/0/android/data/com.tencent.tmgp.pubgmhd/...

  • 解读 :这类路径是Android应用的标准数据存储路径(外部存储的应用私有目录)。它们与Play Integrity无关,但反映了用户或脚本可能尝试访问或修改应用数据。一个健壮的Play Integrity Checker工具,可以扩展功能,例如检查自身应用目录是否被异常访问或篡改,作为额外的安全层,但这属于应用自身防护范畴,而非Play Integrity API的标准功能。

6. 功能扩展与进阶应用

一个基础的Checker工具已经完成。但我们可以让它更强大,成为一个真正的“安全验证工具箱”。

6.1 增加本地缓存与历史记录

每次检查都产生宝贵的验证数据。我们可以将这些结果(时间戳、设备型号、各项完整性结果)保存到本地数据库(如Room),并提供一个历史记录查看界面。这有助于测试人员对比同一设备在不同状态(如Root前、Root后、隐藏Root后)下的验证结果变化。

6.2 集成设备信息收集

在发送令牌到服务器验证的同时,可以附带一些基本的、不涉及隐私的设备信息,如 Build.MODEL , Build.BRAND , Build.VERSION.SDK_INT 等。服务器端在返回验证结果时,可以将这些信息一并记录到日志中。这对于分析哪些设备型号、系统版本更容易出现验证问题非常有帮助。

6.3 模拟“攻击”与绕过检测测试(仅供安全研究)

为了深入理解Play Integrity API的防护能力,你可以在受控环境中进行测试:

  • 使用Magisk Hide/DenyList :在Root设备上,配置Magisk对你的Checker应用隐藏Root状态。观察验证结果是否发生变化。这能帮你了解Play Integrity API检测Root的深度。
  • 在模拟器上安装Google Play服务 :一些修改过的模拟器镜像包含了Google Play服务。在这些模拟器上运行你的Checker,看它能否被识别出来。
  • 使用Xposed/LSPosed模块 :编写或使用现有模块,尝试Hook Play Integrity API的相关调用,返回伪造的“通过”结果。这能帮助你评估API的抗篡改能力。

重要警告 :此类测试应仅限于你自己拥有完全控制权的设备和应用,用于安全研究和提升应用防护。绝对不要对他人应用进行此类测试,这不仅是非法的,也违反Google Play的政策。

6.4 构建自动化测试套件

你可以将Checker工具的核心验证逻辑封装成一个库(Library Module),然后为你主应用的UI自动化测试(使用Espresso或UI Automator)添加一个测试用例:在关键流程(如登录、支付)开始前,自动运行一次完整性检查,并将结果输出到测试日志中。这能在回归测试中持续监控你的应用运行环境是否安全合规。

构建一个完整的Play Integrity Checker工具,远不止是调用一个API那么简单。它迫使你深入理解Android安全模型、客户端-服务端交互、证书管理以及各种设备状态。通过这个过程,你获得的不仅仅是这个工具本身,而是一套应对应用安全、反作弊、渠道保护等现实问题的完整方法论和实战能力。当你再次看到那些试图绕过验证的非常规路径时,你就能更清晰地知道你的防线在哪里,又该如何加固它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值