Android 设备完整性检测实战Play Integrity API Checker 如何用 4 项指标看穿设备真相【免费下载链接】play-integrity-checker-appGet info about your Device Integrity through the Play Intergrity API项目地址: https://gitcode.com/gh_mirrors/pl/play-integrity-checker-appPlay Integrity API Checker 是一款基于 Google 官方 Play Integrity API 的开源检测工具能把设备安全性拆解成 4 项可读的完整性结论并附上原始 JSON 证据几秒钟就能看穿一台 Android 设备的真实状态。对做支付、游戏、企业应用的开发者来说它不仅是测试工具更是一份官方 API 该怎么用的活教材。先讲一个让人后背发凉的场景你的支付 App 上线三个月突然发现某个地区退款率异常飙升。查日志发现大量新用户来自同一批设备指纹——它们都能通过登录、都能完成交易唯一的问题是这些设备要么是刷机 Root 过的要么干脆是云端的模拟器农场。这不是天方夜谭而是移动应用每天都在面对的现实App 能跑起来不代表设备值得信任。Root 设备可以伪造响应、模拟器可以批量养号、Xposed 框架可以 Hook 掉你的任何客户端校验。问题在于你拿什么证明这台设备是它声称的样子Google 的答案是 Play Integrity API由可信环境签名、在云端验证、把结果以完整性裁定verdict的形式交给你。而 Play Integrity API Checker 这个开源项目恰好把这条验证链路完整地拆开摆在了你面前——这比任何文档都直观。点下 Check 按钮之后发生了什么很多开发者对 Play Integrity API 的第一印象是调用一个 SDK 就行但 Play Integrity API Checker 告诉我们完整的验证是一条两端协作的链路客户端只是第一棒。第一步生成一个一次性暗号nonce点击 Check 后应用先做一件事生成 50 位随机字符串作为 nonce也就是本次请求的一次性会话标识。private String generateNonce() { int length 50; String nonce ; String allowed ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789; for (int i 0; i length; i) { nonce nonce.concat(String.valueOf(allowed.charAt( (int) Math.floor(Math.random() * allowed.length())))); } return nonce; }为什么要有 nonce因为完整性裁定结果一旦被截获就可能被重放攻击攻击者录下一次合法响应反复提交。把随机 nonce 绑定进请求服务器就能确认这份裁定是针对我这次提问的而不是别人老早录好的。这是 Play Integrity 设计里最容易被新手跳过、却最要命的一环。第二步向 Google 要一张诚信凭证nonce 就绪后应用通过官方 SDK 请求完整性令牌tokenIntegrityManager integrityManager IntegrityManagerFactory.create(getApplicationContext()); TaskIntegrityTokenResponse task integrityManager.requestIntegrityToken( IntegrityTokenRequest.builder() .setNonce(nonce) .build()); task.addOnSuccessListener(response - sendTokenRequest(response.token()));注意客户端拿到的只是一个不透明的 token里面没有可直接阅读的结论。真正的体检报告藏在 token 的签名里只有持有密钥的服务端才能解开。这引出了整个项目最核心的架构取舍。第三步让服务端当验票员拿到 token 后客户端把它交给自己的服务器由服务端调用 Google 的验证接口解签再把结果返回给 AppRequest request new Request.Builder() .get() .url(BuildConfig.API_URL /api/check?token token) .build();这个客户端只取票、服务端来验票的设计是 Play Integrity API Checker 区别于很多客户端直接解析示例的关键。它的 README 里特意用警告口吻强调生产环境绝不能把完整 JSON 丢给客户端App 只需要收到是/否。一句话小结nonce 防重放、token 防篡改、服务端验签防伪造——三层各司其职缺一环整条信任链就断了。4 项完整性指标到底各自在验什么服务端返回的裁定里最核心的是deviceRecognitionVerdict字段。项目用一行代码把这串裁定翻译成 4 个开关private Integer[] parseValues(String integrity) { return new Integer[]{ integrity.contains(MEETS_BASIC_INTEGRITY) ? 1 : 0, integrity.contains(MEETS_DEVICE_INTEGRITY) ? 1 : 0, integrity.contains(MEETS_STRONG_INTEGRITY) ? 1 : 0, integrity.contains(MEETS_VIRTUAL_INTEGRITY) ? 1 : -1 }; }很多人的误区是这 4 项是一层层递进的强完整性包含弱完整性。实际上它们是独立维度各有各的验证目标和信任等级裁定标识它在验证什么典型失败原因适合的信任场景MEETS_BASIC_INTEGRITY设备是否被篡改Bootloader 解锁、Root设备已 Root 或刷入修改过的系统基础内容类 App 的准入判断MEETS_DEVICE_INTEGRITY是否运行官方签名的系统镜像刷了第三方 ROM、系统签名异常金融类 App 的核心操作校验MEETS_STRONG_INTEGRITY硬件级可信根StrongBox/TEE是否完整硬件被物理篡改或强刷高价值转账、企业数据访问MEETS_VIRTUAL_INTEGRITY设备是否运行在模拟器/虚拟化环境检测到模拟器特征游戏防作弊、批量刷量防护注意代码里最后一个值是-1而不是0当服务端没有返回虚拟完整性字段时界面会显示未知状态并隐藏该行——因为**没检测和检测了但没通过是两码事**混淆它们会得出错误的安全结论。这个细节在项目的主界面里被忠实还原了每项指标以通过 ✅ / 失败 ❌ / 未知 ❔三种状态呈现杜绝了含糊其辞。一句话小结别把 4 项指标当关卡要当体检科目——按业务风险选科目按结果做决策。18 个错误码背后的原因 解决方案三重奏真实世界里API 调用失败是常态。项目最见功力的一点是它把 Play Integrity API 的每种失败都整理成了三段式话术错误码是什么 → 为什么会发生 → 用户该怎么办。private String getErrorMessageText(IntegrityServiceException e) { int errorCode e.getErrorCode(); StringBuilder builder new StringBuilder(); builder.append(String.format(Locale.US, %s (%d), getErrorCodeName(errorCode), errorCode)); String reason getErrorReason(errorCode); if (!reason.isEmpty()) builder.append(\n).append(reason); String solution getErrorSolution(errorCode); if (!solution.isEmpty()) builder.append(\n\n).append(solution); return builder.toString(); }翻译成人话几个高频错误码是这样的错误码一句话原因推荐解法API_NOT_AVAILABLE当前设备/环境不支持 Integrity API更新 Play Store 与 Play ServicesNETWORK_ERROR设备没有可用网络检查网络连接后重试TOO_MANY_REQUESTS请求太频繁被限流降低调用频率稍后重试PLAY_STORE_NOT_FOUND设备没有官方 Play Store安装官方版本 Play StoreNONCE_TOO_SHORTnonce 少于 16 字节加长随机串本项目用 50 位APP_UID_MISMATCH调用方 UID 与包管理记录不一致警惕这通常是攻击迹象PLAY_STORE_ACCOUNT_NOT_FOUND设备未登录 Play 账号引导用户登录 Play Store把这张表抄进你自己的 App错误提示就能从第 42 行抛了个异常升级为请更新 Play Store 后重试——这是用户可感知的体验差异也是生产级工程质量的分水岭。一句话小结错误码映射不是查文档的活儿而是产品体验的一部分——好的错误提示能把一次失败变成一次引导。30 分钟从零跑起来部署清单与避坑提示想亲身体验这套链路克隆项目并配置好配套服务端即可git clone https://gitcode.com/gh_mirrors/pl/play-integrity-checker-app cd play-integrity-checker-app环境要求一览项要求构建工具Android Studio Gradle 8.13项目自带 wrapperJDKJava 17Android SDKminSdk 21targetSdk/compileSdk 36服务端配套的 Play Integrity Checker ServerGoogle CloudPlay Console 中关联 GCP 项目并开启对应完整性级别关键一步把服务端地址注入构建项目通过local.properties注入服务端地址再借 Gradle 的buildConfigField编译进代码避免把服务器地址写死在源码里API_URLhttps://my-awesome-server-url.comProperties properties new Properties() properties.load(project.rootProject.file(local.properties).newDataInputStream()) buildConfigField String, API_URL, \${properties.getProperty(API_URL)}\然后构建调试包./gradlew assembleDebug核心逻辑都集中在 MainActivity.java按 nonce → token → 服务端校验 → 解析 → 展示的顺序阅读即可快速掌握全貌。常见误区与避坑提示这里有几条项目作者特意写在 README 开头的忠告全是实践踩出来的坑侧载sideload安装大概率拿不到完整结果。非 Play Store 渠道安装的 App通常无法获得MEETS_BASIC_INTEGRITY和MEETS_STRONG_INTEGRITY。想验证完整功能请从 Play Store 安装。千万不要照抄把 JSON 发给 App的写法。这个项目是检测工具故意展示全部裁定细节但你的生产 App 若把完整 JSON 下发客户端等于把安全判断权交给了可被逆向的进程。正确姿势服务端判定只回传是/否。完整性检查最好和关键业务动作绑票。单独调一次 API 意义有限把 integrity token 与登录、支付等请求打包发送服务端校验通过才放行才能防住重放与绕过。一句话小结跑通 Demo 是 30 分钟的事而把 Demo 变成生产代码需要先把上面三条红线记牢。进阶把检测工具升维成安全防线当你把 Play Integrity API Checker 当参考实现读完下一步就是把它迁移到自己的业务里。几个建议按优先级排服务端是唯一裁判verdict 的验签、判定、策略执行全部放服务端客户端只当采集器。给关键操作加签把 token 塞进登录或支付请求体服务端校验失败直接拒绝不给重放留窗口。缓存与限流为同一设备短时间内的重复检查做缓存例如 5 分钟窗口并实现令牌桶限流避免触发TOO_MANY_REQUESTS。按风险分级普通浏览用 BASIC 兜底敏感操作升到 DEVICE高价值交易再上 STRONG别让所有请求都走最强校验否则性能和配额都扛不住。监控错误码分布把NETWORK_ERROR、TOO_MANY_REQUESTS、APP_UID_MISMATCH的占比做成指标——异常飙升往往意味着攻击或大规模环境问题正在发生。一句话小结工具的终点不是显示结果而是把结果转成决策决策质量取决于你服务端策略的颗粒度。写在最后回看整个项目它最珍贵的不是那几行调用代码而是一个完整、诚实、可运行的安全验证范例nonce 防重放、token 分离、服务端验签、错误码人性化、边界情况如实呈现。做支付的同学可以把它当准入控制模板做游戏的同学可以借它理解模拟器检测的边界做安全平台的团队则能直接参考它的错误处理体系。如果你也曾在设备到底可不可信这个问题上头疼过去项目主页克隆一份源码点开 MainActivity.java 从头读一遍再顺手给这个开源项目点个 Star——你收获的不只是一段能跑的代码更是一堂关于信任的完整实践课。【免费下载链接】play-integrity-checker-appGet info about your Device Integrity through the Play Intergrity API项目地址: https://gitcode.com/gh_mirrors/pl/play-integrity-checker-app创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考