หน้านี้จะอธิบายวิธีตีความและดำเนินการกับผลการตรวจสอบความสมบูรณ์ที่แสดง ไม่ว่าคุณจะส่งคำขอ API แบบมาตรฐานหรือแบบคลาสสิก ระบบจะแสดงผลการตรวจสอบความสมบูรณ์ในรูปแบบเดียวกันโดยมีเนื้อหาคล้ายกัน ผลการตัดสินเกี่ยวกับความสมบูรณ์จะแสดงข้อมูลเกี่ยวกับความถูกต้องของอุปกรณ์ แอป และบัญชี เซิร์ฟเวอร์ของแอปสามารถใช้เพย์โหลดที่ได้ในคำตัดสินที่ถอดรหัสและยืนยันแล้วเพื่อพิจารณาวิธีที่ดีที่สุดในการดําเนินการหรือคําขอหนึ่งๆ ในแอป
รูปแบบการตัดสินความสมบูรณ์ที่แสดงผล
โดยเพย์โหลดจะเป็น JSON ที่เป็นข้อความธรรมดาและมีสัญญาณความสมบูรณ์ควบคู่ไปกับข้อมูลที่นักพัฒนาแอประบุ
โครงสร้างโดยทั่วไปของเพย์โหลดมีดังนี้
{ requestDetails: { ... } appIntegrity: { ... } deviceIntegrity: { ... } accountDetails: { ... } environmentDetails: { ... } }
ก่อนอื่น คุณต้องตรวจสอบว่าค่าในช่อง requestDetails
ตรงกับค่าของคำขอต้นฉบับก่อนตรวจสอบผลการตรวจสอบความสมบูรณ์แต่ละรายการ ส่วนต่อไปนี้จะอธิบายแต่ละช่องอย่างละเอียด
ช่องขอรายละเอียด
ช่อง requestDetails
มีข้อมูลเกี่ยวกับคำขอ รวมถึงข้อมูลที่ได้รับจากนักพัฒนาแอปใน requestHash
สำหรับคำขอมาตรฐาน และ nonce
สำหรับคำขอแบบคลาสสิก
สําหรับคําขอ API มาตรฐาน
requestDetails: { // Application package name this attestation was requested for. // Note that this field might be spoofed in the middle of the request. requestPackageName: "com.package.name" // Request hash provided by the developer. requestHash: "aGVsbG8gd29scmQgdGhlcmU" // The timestamp in milliseconds when the integrity token // was requested. timestampMillis: "1675655009345" }
ค่าเหล่านี้ควรตรงกับค่าในคำขอต้นฉบับ ดังนั้น ให้ยืนยันส่วน requestDetails
ของเพย์โหลด JSON โดยตรวจสอบว่า requestPackageName
และ requestHash
ตรงกับที่ส่งในคำขอเดิม ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
Kotlin
val requestDetails = JSONObject(payload).getJSONObject("requestDetails") val requestPackageName = requestDetails.getString("requestPackageName") val requestHash = requestDetails.getString("requestHash") val timestampMillis = requestDetails.getLong("timestampMillis") val currentTimestampMillis = ... // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request || !requestHash.equals(expectedRequestHash) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
Java
RequestDetails requestDetails = decodeIntegrityTokenResponse .getTokenPayloadExternal() .getRequestDetails(); String requestPackageName = requestDetails.getRequestPackageName(); String requestHash = requestDetails.getRequestHash(); long timestampMillis = requestDetails.getTimestampMillis(); long currentTimestampMillis = ...; // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request. || !requestHash.equals(expectedRequestHash) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
สำหรับคำขอ API แบบคลาสสิก
requestDetails: { // Application package name this attestation was requested for. // Note that this field might be spoofed in the middle of the // request. requestPackageName: "com.package.name" // base64-encoded URL-safe no-wrap nonce provided by the developer. nonce: "aGVsbG8gd29scmQgdGhlcmU" // The timestamp in milliseconds when the request was made // (computed on the server). timestampMillis: "1617893780" }
ค่าเหล่านี้ควรตรงกับค่าในคำขอต้นฉบับ ดังนั้น ให้ยืนยันส่วน requestDetails
ของเพย์โหลด JSON โดยตรวจสอบว่า requestPackageName
และ nonce
ตรงกับที่ส่งในคำขอเดิม ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
Kotlin
val requestDetails = JSONObject(payload).getJSONObject("requestDetails") val requestPackageName = requestDetails.getString("requestPackageName") val nonce = requestDetails.getString("nonce") val timestampMillis = requestDetails.getLong("timestampMillis") val currentTimestampMillis = ... // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request. See 'Generate a nonce' // section of the doc on how to store/compute the expected nonce. || !nonce.equals(expectedNonce) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
Java
JSONObject requestDetails = new JSONObject(payload).getJSONObject("requestDetails"); String requestPackageName = requestDetails.getString("requestPackageName"); String nonce = requestDetails.getString("nonce"); long timestampMillis = requestDetails.getLong("timestampMillis"); long currentTimestampMillis = ...; // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request. See 'Generate a nonce' // section of the doc on how to store/compute the expected nonce. || !nonce.equals(expectedNonce) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
ช่องความสมบูรณ์ของแอปพลิเคชัน
ฟิลด์ appIntegrity
มีข้อมูลเกี่ยวกับแพ็กเกจ
appIntegrity: { // PLAY_RECOGNIZED, UNRECOGNIZED_VERSION, or UNEVALUATED. appRecognitionVerdict: "PLAY_RECOGNIZED" // The package name of the app. // This field is populated iff appRecognitionVerdict != UNEVALUATED. packageName: "com.package.name" // The sha256 digest of app certificates (base64-encoded URL-safe). // This field is populated iff appRecognitionVerdict != UNEVALUATED. certificateSha256Digest: ["6a6a1474b5cbbb2b1aa57e0bc3"] // The version of the app. // This field is populated iff appRecognitionVerdict != UNEVALUATED. versionCode: "42" }
appRecognitionVerdict
อาจมีค่าดังต่อไปนี้
PLAY_RECOGNIZED
- แอปและใบรับรองตรงกับเวอร์ชันที่เผยแพร่โดย Google Play
UNRECOGNIZED_VERSION
- ใบรับรองหรือชื่อแพ็กเกจไม่ตรงกับบันทึกของ Google Play
UNEVALUATED
- ระบบไม่ได้ประเมินความสมบูรณ์ของแอปพลิเคชัน ไม่เป็นไปตามข้อกําหนดที่จําเป็น เช่น อุปกรณ์ไม่น่าเชื่อถือพอ
ตรวจสอบว่าแอปที่คุณสร้างเป็นแอปที่สร้างโทเค็นดังกล่าว โดยการยืนยันว่าความสมบูรณ์ของแอปพลิเคชันเป็นไปตามที่คาดไว้ ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้
Kotlin
val appIntegrity = JSONObject(payload).getJSONObject("appIntegrity") val appRecognitionVerdict = appIntegrity.getString("appRecognitionVerdict") if (appRecognitionVerdict == "PLAY_RECOGNIZED") { // Looks good! }
Java
JSONObject appIntegrity = new JSONObject(payload).getJSONObject("appIntegrity"); String appRecognitionVerdict = appIntegrity.getString("appRecognitionVerdict"); if (appRecognitionVerdict.equals("PLAY_RECOGNIZED")) { // Looks good! }
นอกจากนี้ คุณยังตรวจสอบชื่อแพ็กเกจแอป เวอร์ชันแอป และใบรับรองแอปด้วยตนเองได้
ช่องความสมบูรณ์ของอุปกรณ์
ช่อง deviceIntegrity
อาจมีค่าเดียว นั่นคือ deviceRecognitionVerdict
ที่มีป้ายกำกับอย่างน้อย 1 รายการซึ่งแสดงถึงประสิทธิภาพของอุปกรณ์ในการบังคับใช้ความสมบูรณ์ของแอป หากอุปกรณ์ไม่ตรงตามเกณฑ์ของป้ายกำกับใดๆ ฟิลด์ deviceIntegrity
จะว่างเปล่า
deviceIntegrity: { // "MEETS_DEVICE_INTEGRITY" is one of several possible values. deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"] }
โดยค่าเริ่มต้น deviceRecognitionVerdict
อาจมีสิ่งต่อไปนี้
MEETS_DEVICE_INTEGRITY
- แอปกำลังทำงานบนอุปกรณ์ที่ขับเคลื่อนโดย Android ที่มีบริการ Google Play อุปกรณ์ผ่านการตรวจสอบความสมบูรณ์ของระบบและเป็นไปตามข้อกําหนดความเข้ากันได้ของ Android
- ว่างเปล่า (ค่าว่าง)
- แอปกำลังทำงานในอุปกรณ์ที่มีสัญญาณการโจมตี (เช่น การฮุก API) หรือการบุกรุกระบบ (เช่น การรูท) หรือแอปไม่ทำงานในอุปกรณ์จริง (เช่น โปรแกรมจำลองที่ไม่ผ่านการตรวจสอบความน่าเชื่อถือของ Google Play)
ตรวจสอบว่า deviceRecognitionVerdict
เป็นไปตามที่คาดไว้ ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้ เพื่อให้มั่นใจว่าโทเค็นมาจากอุปกรณ์ที่เชื่อถือได้
Kotlin
val deviceIntegrity = JSONObject(payload).getJSONObject("deviceIntegrity") val deviceRecognitionVerdict = if (deviceIntegrity.has("deviceRecognitionVerdict")) { deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString() } else { "" } if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) { // Looks good! }
Java
JSONObject deviceIntegrity = new JSONObject(payload).getJSONObject("deviceIntegrity"); String deviceRecognitionVerdict = deviceIntegrity.has("deviceRecognitionVerdict") ? deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString() : ""; if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) { // Looks good! }
หากอุปกรณ์ทดสอบไม่เป็นไปตามความสมบูรณ์ของอุปกรณ์ ให้ตรวจสอบว่าได้ติดตั้ง ROM ของโรงงาน (เช่น โดยการรีเซ็ตอุปกรณ์) และบูตโหลดเดอร์ถูกล็อก นอกจากนี้ คุณยังสร้างการทดสอบ Play Integrity API ใน Play Console ได้ด้วย
ป้ายกำกับอุปกรณ์แบบมีเงื่อนไข
หากแอปของคุณเผยแพร่ใน Google Play Games สำหรับ PC deviceRecognitionVerdict
อาจมีป้ายกำกับต่อไปนี้ด้วย
MEETS_VIRTUAL_INTEGRITY
- แอปกำลังทำงานบนโปรแกรมจำลองที่ขับเคลื่อนโดย Android ที่มีบริการ Google Play โปรแกรมจำลองผ่านการตรวจสอบความสมบูรณ์ของระบบและเป็นไปตามข้อกำหนดหลักด้านความเข้ากันได้ของ Android
ข้อมูลอุปกรณ์ที่ไม่บังคับ
หากคุณเลือกใช้ป้ายกำกับเพิ่มเติมในการตัดสินความสมบูรณ์ deviceRecognitionVerdict
จะมีป้ายกำกับเพิ่มเติมต่อไปนี้
MEETS_BASIC_INTEGRITY
- แอปกำลังทำงานบนอุปกรณ์ที่ผ่านการตรวจสอบความสมบูรณ์ของระบบพื้นฐาน อุปกรณ์อาจไม่ตรงตามข้อกําหนดความเข้ากันได้ของ Android และอาจไม่ได้รับอนุมัติให้เรียกใช้บริการ Google Play เช่น อุปกรณ์อาจใช้ Android เวอร์ชันที่ไม่รู้จัก อาจมี Bootloader ที่ปลดล็อกแล้ว หรืออาจไม่ได้รับการรับรองจากผู้ผลิต
MEETS_STRONG_INTEGRITY
- แอปกำลังทำงานบนอุปกรณ์ที่ขับเคลื่อนโดย Android ที่มีบริการ Google Play และมีการรับประกันความสมบูรณ์ของระบบที่เข้มงวด เช่น หลักฐานความสมบูรณ์ของการบูตที่รองรับฮาร์ดแวร์ อุปกรณ์ผ่านการตรวจสอบความสมบูรณ์ของระบบและเป็นไปตามข้อกําหนดความเข้ากันได้ของ Android
อุปกรณ์เครื่องเดียวจะแสดงป้ายกำกับอุปกรณ์หลายรายการในผลการตัดสินความสมบูรณ์ของอุปกรณ์ หากตรงตามเกณฑ์ของแต่ละป้ายกำกับ
กิจกรรมล่าสุดในอุปกรณ์
นอกจากนี้ คุณยังเลือกรับกิจกรรมล่าสุดในอุปกรณ์ได้ด้วย ซึ่งจะบอกจำนวนครั้งที่แอปของคุณร้องขอโทเค็นความสมบูรณ์ในอุปกรณ์ที่ระบุในชั่วโมงที่ผ่านมา คุณสามารถใช้กิจกรรมล่าสุดในอุปกรณ์เพื่อปกป้องแอปจากอุปกรณ์ที่ทำงานผิดปกติและทำงานหนักเกินปกติ ซึ่งอาจเป็นสัญญาณของการโจมตีที่กำลังดำเนินอยู่ คุณเลือกระดับความน่าเชื่อถือของกิจกรรมล่าสุดในอุปกรณ์แต่ละระดับได้โดยอิงตามจำนวนครั้งที่คุณคาดหวังว่าแอปที่ติดตั้งในอุปกรณ์ทั่วไปจะขอโทเค็นความสมบูรณ์ในแต่ละชั่วโมง
หากคุณเลือกใช้เพื่อรับ recentDeviceActivity
ฟิลด์ deviceIntegrity
จะมีค่า 2 ค่าดังนี้
deviceIntegrity: { deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"] recentDeviceActivity: { // "LEVEL_2" is one of several possible values. deviceActivityLevel: "LEVEL_2" } }
คําจํากัดความของ deviceActivityLevel
จะแตกต่างกันไปตามโหมดและอาจมีค่าใดค่าหนึ่งต่อไปนี้
ระดับกิจกรรมล่าสุดในอุปกรณ์ | คำขอโทเค็นความสมบูรณ์ของ API มาตรฐานในอุปกรณ์นี้ในชั่วโมงที่ผ่านมาต่อแอป | คำขอโทเค็นความสมบูรณ์ของ API แบบคลาสสิกในอุปกรณ์นี้ในชั่วโมงที่ผ่านมาต่อแอป |
---|---|---|
LEVEL_1 (ต่ำสุด) |
ไม่เกิน 10 | 5 หรือน้อยกว่า |
LEVEL_2 |
ระหว่าง 11 ถึง 25 | ระหว่าง 6 ถึง 10 |
LEVEL_3 |
ระหว่าง 26 ถึง 50 | ระหว่าง 11 ถึง 15 |
LEVEL_4 (สูงสุด) |
มากกว่า 50 | มากกว่า 15 |
UNEVALUATED |
ระบบไม่ได้ประเมินกิจกรรมล่าสุดในอุปกรณ์ ซึ่งอาจเกิดขึ้นเนื่องจากเหตุผลต่อไปนี้
|
แอตทริบิวต์อุปกรณ์
นอกจากนี้ คุณยังเลือกใช้แอตทริบิวต์อุปกรณ์ได้ด้วย ซึ่งจะระบุเวอร์ชัน Android SDK ของระบบปฏิบัติการ Android ที่ทำงานในอุปกรณ์ ในอนาคต เราอาจขยายแอตทริบิวต์นี้ด้วยแอตทริบิวต์อุปกรณ์อื่นๆ
ค่าเวอร์ชัน SDK คือหมายเลขเวอร์ชัน Android SDK ที่กําหนดไว้ใน
Build.VERSION_CODES
ระบบจะไม่ประเมินเวอร์ชัน SDK หากไม่เป็นไปตามข้อกําหนดที่จําเป็น ในกรณีนี้ จะไม่มีการตั้งค่าในช่อง sdkVersion
ดังนั้นช่อง deviceAttributes
จึงว่างเปล่า
ปัญหานี้อาจเกิดขึ้นเนื่องจากสาเหตุต่อไปนี้
- อุปกรณ์ไม่น่าเชื่อถือพอ
- Google Play ไม่รู้จักเวอร์ชันของแอปที่ติดตั้งในอุปกรณ์
- อุปกรณ์มีปัญหาทางเทคนิค
หากคุณเลือกใช้ deviceAttributes
ฟิลด์ deviceIntegrity
จะมีช่องเพิ่มเติมต่อไปนี้
deviceIntegrity: { deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"] deviceAttributes: { // 33 is one possible value, which represents Android 13 (Tiramisu). sdkVersion: 33 } }
ในกรณีที่ไม่ได้ประเมินเวอร์ชัน SDK ระบบจะตั้งค่าช่อง deviceAttributes
ดังนี้
deviceIntegrity: { deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"] deviceAttributes: {} // sdkVersion field is not set. }
ช่องรายละเอียดบัญชี
ช่อง accountDetails
มีค่าเดียวคือ appLicensingVerdict
ซึ่งแสดงสถานะการอนุญาตให้ใช้สิทธิ Google Play ของแอปสำหรับบัญชีผู้ใช้ที่ลงชื่อเข้าใช้ในอุปกรณ์ หากบัญชีผู้ใช้มีใบอนุญาต Play สำหรับแอป แสดงว่าผู้ใช้ดาวน์โหลดหรือซื้อแอปจาก Google Play
accountDetails: { // This field can be LICENSED, UNLICENSED, or UNEVALUATED. appLicensingVerdict: "LICENSED" }
appLicensingVerdict
อาจมีค่าใดค่าหนึ่งต่อไปนี้
LICENSED
- ผู้ใช้มีสิทธิ์ในการใช้แอป กล่าวคือ ผู้ใช้ได้ติดตั้งหรืออัปเดตแอปของคุณจาก Google Play ในอุปกรณ์
UNLICENSED
- ผู้ใช้ไม่มีสิทธิ์ในการใช้แอป กรณีเช่นนี้เกิดขึ้นเมื่อผู้ใช้โหลดแอปของคุณจากแหล่งที่ไม่รู้จัก หรือไม่ได้ดาวน์โหลดแอปจาก Google Play เป็นต้น คุณสามารถแสดงกล่องโต้ตอบ GET_LICENSED แก่ผู้ใช้เพื่อแก้ไขปัญหานี้ได้
UNEVALUATED
ระบบไม่ได้ประเมินรายละเอียดการอนุญาตให้ใช้สิทธิ เนื่องจากไม่เป็นไปตามข้อกําหนดที่จําเป็น
ปัญหานี้อาจเกิดขึ้นได้จากหลายสาเหตุ เช่น
- อุปกรณ์ไม่น่าเชื่อถือพอ
- Google Play ไม่รู้จักเวอร์ชันของแอปที่ติดตั้งในอุปกรณ์
- ผู้ใช้ไม่ได้ลงชื่อเข้าใช้ Google Play
หากต้องการตรวจสอบว่าผู้ใช้มีสิทธิ์ของแอปสำหรับแอปของคุณ ให้ยืนยันว่า appLicensingVerdict
เป็นไปตามที่คาดไว้ ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
Kotlin
val accountDetails = JSONObject(payload).getJSONObject("accountDetails") val appLicensingVerdict = accountDetails.getString("appLicensingVerdict") if (appLicensingVerdict == "LICENSED") { // Looks good! }
Java
JSONObject accountDetails = new JSONObject(payload).getJSONObject("accountDetails"); String appLicensingVerdict = accountDetails.getString("appLicensingVerdict"); if (appLicensingVerdict.equals("LICENSED")) { // Looks good! }
ฟิลด์รายละเอียดสภาพแวดล้อม
นอกจากนี้ คุณยังเลือกใช้สัญญาณเพิ่มเติมเกี่ยวกับสภาพแวดล้อมได้ด้วย ความเสี่ยงในการเข้าถึงแอปจะบอกให้แอปทราบว่ามีแอปอื่นๆ ทำงานอยู่ซึ่งอาจใช้เพื่อจับภาพหน้าจอ แสดงซ้อนทับแอป หรือควบคุมอุปกรณ์หรือไม่ ผลการตัดสินของ Play Protect จะบอกคุณว่า Google Play Protect เปิดใช้ในอุปกรณ์หรือไม่ และพบมัลแวร์ที่รู้จักหรือไม่
หากคุณเลือกรับผลการตัดสินความเสี่ยงการเข้าถึงแอปหรือผลการตัดสินของ Play Protect ใน Google Play Console การตอบกลับจาก API จะมีช่องenvironmentDetails
ฟิลด์ environmentDetails
อาจมีค่า 2 ค่า ได้แก่ appAccessRiskVerdict
และ playProtectVerdict
คำตัดสินความเสี่ยงในการเข้าถึงแอป
เมื่อเปิดใช้แล้ว ช่อง environmentDetails
ใน Play Integrity API
payload จะมีผลการตัดสินความเสี่ยงในการเข้าถึงแอปใหม่
{
requestDetails: { ... }
appIntegrity: { ... }
deviceIntegrity: { ... }
accountDetails: { ... }
environmentDetails: {
appAccessRiskVerdict: {
// This field contains one or more responses, for example the following.
appsDetected: ["KNOWN_INSTALLED", "UNKNOWN_INSTALLED", "UNKNOWN_CAPTURING"]
}
}
}
หากมีการประเมินความเสี่ยงการเข้าถึงแอป appAccessRiskVerdict
จะมีช่อง
appsDetected
ที่มีคำตอบอย่างน้อย 1 รายการ การตอบกลับเหล่านี้จะจัดอยู่ในกลุ่มใดกลุ่มหนึ่งต่อไปนี้ โดยขึ้นอยู่กับแหล่งที่มาของการติดตั้งแอปที่ตรวจพบ
แอป Play หรือแอประบบ: แอปที่ Google Play ติดตั้งหรือผู้ผลิตอุปกรณ์โหลดไว้ล่วงหน้าในพาร์ติชันระบบของอุปกรณ์ (ระบุด้วย
FLAG_SYSTEM
) การตอบกลับสําหรับแอปดังกล่าวจะมีKNOWN_
อยู่หน้าคำตอบแอปอื่นๆ: แอปที่ Google Play ไม่ได้ติดตั้ง โดยไม่รวมแอปที่ผู้ผลิตอุปกรณ์โหลดไว้ล่วงหน้าในพาร์ทิชันระบบ การตอบกลับสำหรับแอปดังกล่าวจะมี
UNKNOWN_
นำหน้า
ระบบจะแสดงผลลัพธ์ต่อไปนี้
KNOWN_INSTALLED
,UNKNOWN_INSTALLED
- มีการติดตั้งแอปที่ตรงกับแหล่งที่มาของการติดตั้งที่เกี่ยวข้อง
KNOWN_CAPTURING
,UNKNOWN_CAPTURING
- มีแอปที่ทำงานอยู่ซึ่งเปิดใช้สิทธิ์ที่อาจใช้เพื่อดูหน้าจอขณะที่แอปของคุณทำงานอยู่ ซึ่งไม่รวมบริการการช่วยเหลือพิเศษที่ผ่านการยืนยันแล้วซึ่ง Google Play ทราบว่าทำงานอยู่ในอุปกรณ์
KNOWN_CONTROLLING
,UNKNOWN_CONTROLLING
- มีแอปที่ทำงานอยู่ซึ่งเปิดใช้สิทธิ์ที่อาจใช้เพื่อควบคุมอุปกรณ์และควบคุมอินพุตไปยังแอปของคุณโดยตรง รวมถึงอาจใช้เพื่อบันทึกอินพุตและเอาต์พุตของแอป โดยไม่รวมบริการการช่วยเหลือพิเศษที่ผ่านการยืนยันซึ่ง Google Play ทราบว่าทำงานอยู่ในอุปกรณ์
KNOWN_OVERLAYS
,UNKNOWN_OVERLAYS
- มีแอปที่ทำงานอยู่ซึ่งเปิดใช้สิทธิ์ที่อาจใช้เพื่อแสดงการวางซ้อนบนแอปของคุณ โดยไม่รวมบริการการช่วยเหลือพิเศษที่ได้รับการยืนยันซึ่ง Google Play ทราบว่าทำงานอยู่ในอุปกรณ์
- ว่างเปล่า (ค่าว่าง)
ระบบจะไม่ประเมินความเสี่ยงในการเข้าถึงแอปหากไม่เป็นไปตามข้อกําหนดที่จําเป็น ในกรณีนี้ ช่อง
appAccessRiskVerdict
จะว่างเปล่า ปัญหานี้อาจเกิดขึ้นได้จากหลายสาเหตุ เช่น- อุปกรณ์ไม่น่าเชื่อถือพอ
- รูปแบบของอุปกรณ์ไม่ใช่โทรศัพท์ แท็บเล็ต หรือแบบพับได้
- อุปกรณ์ไม่ได้ใช้ Android 6 (API ระดับ 23) ขึ้นไป
- Google Play ไม่รู้จักเวอร์ชันของแอปที่ติดตั้งในอุปกรณ์
- Google Play Store ในอุปกรณ์เป็นเวอร์ชันล้าสมัย
- เกมเท่านั้น: บัญชีผู้ใช้ไม่มีใบอนุญาต Play สำหรับเกม
- ใช้คําขอมาตรฐานกับพารามิเตอร์
verdictOptOut
- มีการใช้คําขอมาตรฐานกับไลบรารี Play Integrity API เวอร์ชันที่ยังไม่รองรับความเสี่ยงในการเข้าถึงแอปสําหรับคําขอมาตรฐาน
ความเสี่ยงในการเข้าถึงแอปจะยกเว้นบริการการช่วยเหลือพิเศษที่ได้รับการยืนยันแล้วโดยอัตโนมัติ ซึ่งผ่านการตรวจสอบการช่วยเหลือพิเศษที่ปรับปรุงแล้วของ Google Play (ติดตั้งโดย App Store ใดก็ได้ในอุปกรณ์) "ยกเว้น" หมายความว่าบริการการช่วยเหลือพิเศษที่ยืนยันแล้วซึ่งทำงานอยู่ในอุปกรณ์จะไม่แสดงการตอบกลับการจับภาพ การควบคุม หรือการวางซ้อนในผลการตัดสินความเสี่ยงการเข้าถึงแอป หากต้องการขอรับการตรวจสอบการช่วยเหลือพิเศษที่เพิ่มประสิทธิภาพของ Google Play สำหรับแอปการช่วยเหลือพิเศษ ให้เผยแพร่แอปใน Google Play โดยตรวจสอบว่าแอปตั้งค่า Flag isAccessibilityTool
เป็น "จริง" ในไฟล์ Manifest ของแอป หรือขอรับการตรวจสอบ
ตารางต่อไปนี้แสดงตัวอย่างคำตัดสินและความหมาย (ตารางนี้ไม่ได้แสดงผลลัพธ์ที่เป็นไปได้ทั้งหมด)
ตัวอย่างคำตัดสินความเสี่ยงในการเข้าถึงแอป | การตีความ |
---|---|
appsDetected: ["KNOWN_INSTALLED"]
|
มีเพียงแอปที่ Google Play รู้จักหรือผู้ผลิตอุปกรณ์โหลดไว้ล่วงหน้าในพาร์ติชันระบบเท่านั้น ไม่มีแอปใดทำงานอยู่ซึ่งจะส่งผลให้มีการตัดสินการจับภาพ การควบคุม หรือการวางซ้อน |
appsDetected: ["KNOWN_INSTALLED", "UNKNOWN_INSTALLED", "UNKNOWN_CAPTURING"]
|
มีแอปที่ Google Play ติดตั้งหรือผู้ผลิตอุปกรณ์โหลดไว้ล่วงหน้าในพาร์ติชันระบบ มีแอปอื่นๆ ที่ทำงานอยู่และเปิดใช้สิทธิ์ที่อาจใช้เพื่อดูหน้าจอหรือจับภาพอินพุตและเอาต์พุตอื่นๆ |
appsDetected: ["KNOWN_INSTALLED", "KNOWN_CAPTURING", "UNKNOWN_INSTALLED", "UNKNOWN_CONTROLLING"]
|
มี Play หรือระบบที่ทำงานอยู่ซึ่งเปิดใช้สิทธิ์ที่อาจใช้เพื่อดูหน้าจอหรือจับภาพอินพุตและเอาต์พุตอื่นๆ นอกจากนี้ยังมีแอปอื่นๆ ที่ทำงานอยู่ซึ่งเปิดใช้สิทธิ์ที่อาจใช้เพื่อควบคุมอุปกรณ์และควบคุมอินพุตไปยังแอปของคุณได้โดยตรง |
appAccessRiskVerdict: {}
|
ระบบไม่ได้ประเมินความเสี่ยงการเข้าถึงแอปเนื่องจากไม่เป็นไปตามข้อกําหนดที่จําเป็น เช่น อุปกรณ์ไม่น่าเชื่อถือพอ |
คุณเลือกชุดค่าผสมของคำตัดสินที่ยอมรับได้เพื่อดำเนินการต่อและคำตัดสินที่ต้องการดำเนินการได้ ทั้งนี้ขึ้นอยู่กับระดับความเสี่ยง ตัวอย่างโค้ดต่อไปนี้แสดงการยืนยันว่าไม่มีแอปใดทำงานอยู่ซึ่งอาจจับภาพหน้าจอหรือควบคุมแอปของคุณ
Kotlin
val environmentDetails = JSONObject(payload).getJSONObject("environmentDetails") val appAccessRiskVerdict = environmentDetails.getJSONObject("appAccessRiskVerdict") if (appAccessRiskVerdict.has("appsDetected")) { val appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString() if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) { // Looks good! } }
Java
JSONObject environmentDetails = new JSONObject(payload).getJSONObject("environmentDetails"); JSONObject appAccessRiskVerdict = environmentDetails.getJSONObject("appAccessRiskVerdict"); if (appAccessRiskVerdict.has("appsDetected")) { String appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString() if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) { // Looks good! } }
แก้ไขคำตัดสินความเสี่ยงในการเข้าถึงแอป
คุณเลือกได้ว่าต้องการดำเนินการกับคำตัดสินความเสี่ยงในการเข้าถึงแอปใดก่อนอนุญาตให้ผู้ใช้ส่งคำขอหรือดำเนินการให้เสร็จสมบูรณ์ ทั้งนี้ขึ้นอยู่กับระดับความเสี่ยง คุณสามารถแสดงพรอมต์ของ Google Play ให้แก่ผู้ใช้ได้ (ไม่บังคับ) หลังจากที่ตรวจสอบคำตัดสินความเสี่ยงในการเข้าถึงแอปแล้ว คุณสามารถแสดง CLOSE_UNKNOWN_ACCESS_RISK เพื่อขอให้ผู้ใช้ปิดแอปที่ไม่รู้จักซึ่งทําให้เกิดคำตัดสินความเสี่ยงในการเข้าถึงแอป หรือจะแสดง CLOSE_ALL_ACCESS_RISK เพื่อขอให้ผู้ใช้ปิดแอปทั้งหมด (ทั้งแอปที่รู้จักและไม่รู้จัก) ซึ่งทําให้เกิดคำตัดสินความเสี่ยงในการเข้าถึงแอปก็ได้
ผลการตรวจสอบของ Play Protect
เมื่อเปิดใช้แล้ว ช่อง environmentDetails
ในPlay Integrity API
พายโหลดจะมีผลการตัดสินของ Play Protect ดังนี้
environmentDetails: {
playProtectVerdict: "NO_ISSUES"
}
playProtectVerdict
อาจมีค่าใดค่าหนึ่งต่อไปนี้
NO_ISSUES
- Play Protect เปิดอยู่และไม่พบปัญหาเกี่ยวกับแอปในอุปกรณ์
NO_DATA
- Play Protect เปิดอยู่แต่ยังไม่มีการสแกน อุปกรณ์หรือแอป Play Store อาจเพิ่งรีเซ็ต
POSSIBLE_RISK
- Play Protect ปิดอยู่
MEDIUM_RISK
- Play Protect เปิดอยู่และพบแอปที่อาจเป็นอันตรายซึ่งติดตั้งในอุปกรณ์
HIGH_RISK
- Play Protect เปิดอยู่และพบแอปที่เป็นอันตรายซึ่งติดตั้งอยู่ในอุปกรณ์
UNEVALUATED
ระบบไม่ได้ประเมินคำตัดสินของ Play Protect
ปัญหานี้อาจเกิดขึ้นได้จากหลายสาเหตุ เช่น
- อุปกรณ์ไม่น่าเชื่อถือพอ
- เกมเท่านั้น: บัญชีผู้ใช้ไม่มีใบอนุญาต Play สำหรับเกม
คำแนะนำในการใช้ผลการตรวจสอบของ Play Protect
เซิร์ฟเวอร์แบ็กเอนด์ของแอปสามารถเลือกได้ว่าต้องดำเนินการอย่างไรโดยอิงตามคำตัดสินตามระดับความเสี่ยงที่ยอมรับ คำแนะนำและการดําเนินการที่ผู้ใช้อาจทำมีดังนี้
NO_ISSUES
- Play Protect เปิดอยู่และไม่พบปัญหาใดๆ ผู้ใช้จึงไม่ต้องดำเนินการใดๆ
POSSIBLE_RISK
และNO_DATA
- เมื่อได้รับผลการตรวจสอบเหล่านี้แล้ว ให้ขอให้ผู้ใช้ตรวจสอบว่า Play Protect เปิดอยู่และได้ทำการสแกนแล้ว
NO_DATA
ควรปรากฏเฉพาะในบางกรณีเท่านั้น MEDIUM_RISK
และHIGH_RISK
- คุณสามารถขอให้ผู้ใช้เปิด Play Protect และดำเนินการกับคำเตือนของ Play Protect ทั้งนี้ขึ้นอยู่กับระดับความเสี่ยงที่ยอมรับ หากผู้ใช้ไม่สามารถปฏิบัติตามข้อกําหนดเหล่านี้ คุณสามารถบล็อกผู้ใช้ไม่ให้ดําเนินการกับเซิร์ฟเวอร์ได้