สร้างคำขอ API แบบคลาสสิก

หากคุณวางแผนที่จะสร้าง API มาตรฐานเท่านั้น ของคำขอ ซึ่งเหมาะสำหรับผู้ใช้ส่วนใหญ่ นักพัฒนาซอฟต์แวร์คุณสามารถข้ามไปที่ความซื่อสัตย์ คำตัดสิน หน้านี้อธิบายการสร้างแบบคลาสสิก คําขอ API สําหรับการตัดสินความสมบูรณ์ ซึ่งรองรับใน Android 4.4 (API ระดับ 19) ขึ้นไป

ข้อควรพิจารณา

เปรียบเทียบคำขอมาตรฐานและคำขอแบบคลาสสิก

คุณสามารถสร้างคำขอมาตรฐาน คำขอแบบคลาสสิก หรือทั้ง 2 อย่างรวมกันก็ได้ ตามความต้องการด้านความปลอดภัยและการป้องกันการละเมิดของแอป คำขอมาตรฐานคือ เหมาะสำหรับแอปและเกมทั้งหมด และสามารถใช้เพื่อตรวจสอบว่า การเรียกใช้เซิร์ฟเวอร์เป็นความจริง ขณะมอบการป้องกันบางอย่างไม่ให้สามารถเล่นซ้ำได้ และการขโมยข้อมูลไปยัง Google Play คำขอแบบคลาสสิกมีราคาแพงกว่าและ คุณต้องรับผิดชอบการติดตั้งใช้งาน บรรทัดดังกล่าวอย่างถูกต้องเพื่อป้องกัน การขโมยข้อมูลและการโจมตีบางประเภท ควรส่งคำขอแบบคลาสสิกน้อยลง บ่อยกว่าคำขอมาตรฐาน เช่น เป็นแบบครั้งเดียวเพื่อตรวจสอบ การกระทำที่มีคุณค่าสูงหรือมีความละเอียดอ่อนเป็นการกระทำจริงหรือไม่

ตารางต่อไปนี้จะเน้นความแตกต่างที่สำคัญระหว่าง คำขอ:

คําขอ API มาตรฐาน คําขอ API แบบคลาสสิก
สิ่งที่ต้องมีก่อน
ต้องมีเวอร์ชัน Android SDK ขั้นต่ำ Android 5.0 (API ระดับ 21) ขึ้นไป Android 4.4 (API ระดับ 19) ขึ้นไป
ข้อกำหนดของ Google Play Google Play Store และบริการ Google Play Google Play Store และบริการ Google Play
รายละเอียดการผสานรวม
ต้องอุ่นเครื่อง API ✔️ (ไม่กี่วินาที)
เวลาในการตอบสนองคำขอโดยทั่วไป ไม่กี่ร้อยมิลลิวินาที ไม่กี่วินาที
ความถี่ของคำขอที่เป็นไปได้ บ่อย (การตรวจสอบการดำเนินการหรือคำขอตามคำขอ) ไม่บ่อย (การตรวจสอบแบบครั้งเดียวสำหรับการดำเนินการที่มีมูลค่าสูงสุดหรือคำขอที่มีความละเอียดอ่อนมากที่สุด)
หมดเวลา อุ่นเครื่องส่วนใหญ่จะสั้นกว่า 10 วินาที แต่เกี่ยวข้องกับการเรียกใช้เซิร์ฟเวอร์ เราจึงขอแนะนำให้ใช้ระยะหมดเวลาที่นาน (เช่น 1 นาที) คำขอคำตัดสินเกิดขึ้นจากฝั่งไคลเอ็นต์ คำขอส่วนใหญ่ต่ำกว่า 10 วินาที แต่เกี่ยวข้องกับการเรียกใช้เซิร์ฟเวอร์ ดังนั้นขอแนะนำให้ตั้งระยะหมดเวลาที่นาน (เช่น 1 นาที)
โทเค็นการตัดสินความสมบูรณ์
มีรายละเอียดอุปกรณ์ แอป และบัญชี ✔️ ✔️
การแคชโทเค็น การแคชในอุปกรณ์ที่ได้รับการคุ้มครองโดย Google Play ไม่แนะนำ
ถอดรหัสและยืนยันโทเค็นผ่านเซิร์ฟเวอร์ Google Play ✔️ ✔️
เวลาในการตอบสนองของคำขอถอดรหัสแบบเซิร์ฟเวอร์ต่อเซิร์ฟเวอร์ตามปกติ 10 วินาทีของมิลลิวินาทีที่มีความพร้อมใช้งาน 3-9 วินาที 10 วินาทีของมิลลิวินาทีที่มีความพร้อมใช้งาน 3-9 วินาที
ถอดรหัสและยืนยันโทเค็นในเครื่องในสภาพแวดล้อมเซิร์ฟเวอร์ที่ปลอดภัย ✔️
ถอดรหัสและยืนยันโทเค็นฝั่งไคลเอ็นต์
ความใหม่ของการตัดสินความสมบูรณ์ Google Play จะแคชและรีเฟรชอัตโนมัติบางส่วน คำตัดสินทั้งหมดที่คำนวณใหม่สำหรับคำขอแต่ละรายการ
ข้อจำกัด
คำขอต่อแอปต่อวัน 10,000 รายการโดยค่าเริ่มต้น (ขอเพิ่มได้) 10,000 รายการโดยค่าเริ่มต้น (ขอเพิ่มได้)
คำขอต่ออินสแตนซ์แอปต่อนาที อุ่นเครื่อง: 5 ครั้งต่อนาที
โทเค็นความสมบูรณ์: ไม่มีขีดจำกัดสาธารณะ*
โทเค็นความสมบูรณ์: 5 ต่อนาที
การป้องกัน
ป้องกันการปลอมแปลงและการโจมตีในลักษณะเดียวกัน ใช้ช่อง requestHash ใช้ช่อง nonce กับการเชื่อมโยงเนื้อหาตามข้อมูลคำขอ
ลดการต่อต้านการเล่นซ้ำและการโจมตีที่คล้ายกัน การผ่อนปรนชั่วคราวโดย Google Play ใช้ช่อง nonce กับตรรกะฝั่งเซิร์ฟเวอร์

* คำขอทั้งหมด รวมถึงคำขอที่ไม่จำกัดแบบสาธารณะ อยู่ภายใต้ขีดจำกัดการป้องกันที่ไม่เปิดเผยต่อสาธารณะ

สร้างคำขอแบบคลาสสิกไม่บ่อย

การสร้างโทเค็นความสมบูรณ์ต้องใช้เวลา ข้อมูล และแบตเตอรี่ และแต่ละแอปจะมี จำนวนคำขอแบบคลาสสิกสูงสุดที่สร้างได้ต่อวัน ดังนั้นคุณควร สร้างเฉพาะคำขอแบบคลาสสิกเพื่อตรวจสอบมูลค่าสูงสุดหรือการดำเนินการที่มีความละเอียดอ่อนที่สุด เป็นของแท้เมื่อคุณต้องการให้การรับประกันเพิ่มเติมสำหรับคำขอมาตรฐาน คุณ ไม่ควรส่งคำขอแบบเดิมสำหรับการดำเนินการที่ใช้ความถี่สูงหรือมูลค่าต่ำ สิ่งที่ไม่ควรทำ ส่งคำขอแบบคลาสสิกทุกครั้งที่แอปย้ายไปยังเบื้องหน้าหรือทุก 2-3 ใช้งานในเบื้องหลัง และหลีกเลี่ยงการโทรจากอุปกรณ์จำนวนมากใน ในเวลาเดียวกัน แอปที่ส่งคำขอแบบคลาสสิกมากเกินไปอาจถูกควบคุมให้ เพื่อปกป้องผู้ใช้จากการติดตั้งใช้งานที่ไม่ถูกต้อง

หลีกเลี่ยงการแคชคำตัดสิน

การแคชผลการตัดสินจะเพิ่มความเสี่ยงของการโจมตี เช่น การขโมยข้อมูล และการเล่นซ้ำ ที่จะนำคำตัดสินที่ดีมาใช้ซ้ำจากสภาพแวดล้อมที่ไม่น่าเชื่อถือ หากคุณ ให้พิจารณาส่งคำขอแบบคลาสสิก แล้วแคชไว้ใช้ในภายหลัง แนะนำให้ส่งคำขอมาตรฐานแบบออนดีมานด์แทน คำขอมาตรฐาน เกี่ยวข้องกับการแคชบางส่วนในอุปกรณ์ แต่ Google Play ใช้การปกป้องเพิ่มเติม เทคนิคที่ช่วยลดความเสี่ยงของการโจมตีซ้ำและการขโมยข้อมูล

ใช้ช่อง Nonce เพื่อปกป้องคำขอแบบคลาสสิก

Play Integrity API มีช่องชื่อ nonce ซึ่งสามารถใช้เพื่อ ปกป้องแอปของคุณจากการโจมตีบางอย่างเพิ่มเติม เช่น การเล่นซ้ำและการสร้างความเสียหาย การโจมตี Play Integrity API จะแสดงค่าที่คุณตั้งค่าไว้ในช่องนี้ภายใน การตอบกลับด้านความสมบูรณ์ที่ลงนามแล้ว ปฏิบัติตามคำแนะนำอย่างละเอียดเกี่ยวกับวิธีสร้าง nonces สำหรับปกป้องแอปของคุณจากการโจมตี

ลองส่งคำขอแบบคลาสสิกอีกครั้งด้วย Exponential Backoff

สภาวะแวดล้อม เช่น การเชื่อมต่ออินเทอร์เน็ตที่ไม่เสถียรหรือ อุปกรณ์ทำงานหนักเกินไป อาจทำให้การตรวจสอบความสมบูรณ์ของอุปกรณ์ล้มเหลว ซึ่งอาจส่งผลถึง ไม่มีการสร้างป้ายกำกับสำหรับอุปกรณ์ที่เชื่อถือได้ ถึง คุณสามารถลดสถานการณ์เหล่านี้ได้ โดยให้รวมตัวเลือกการลองอีกครั้งที่มี Exponential Backoff

ภาพรวม

แผนภาพลำดับที่แสดงการออกแบบระดับสูงของ Play Integrity
API

เมื่อผู้ใช้ดำเนินการที่มีมูลค่าสูงในแอปซึ่งคุณต้องการปกป้อง ด้วยการตรวจสอบความสมบูรณ์ ให้ทำตามขั้นตอนต่อไปนี้

  1. แบ็กเอนด์ฝั่งเซิร์ฟเวอร์ของแอปจะสร้างและส่งค่าที่ไม่ซ้ำกันไปยัง และฝั่งไคลเอ็นต์ ขั้นตอนที่เหลือจะอ้างอิงตรรกะนี้ว่า "แอป"
  2. แอปของคุณสร้าง nonce จากค่าที่ไม่ซ้ำกันและเนื้อหา การกระทำที่มีมูลค่าสูง จากนั้นจะเรียก Play Integrity API ซึ่งจะส่งใน nonce
  3. แอปของคุณได้รับผลการตัดสินที่ลงนามและเข้ารหัสจาก Play Integrity API
  4. แอปของคุณส่งผลการตัดสินที่ลงนามและเข้ารหัสไปยังแบ็กเอนด์ของแอปแล้ว
  5. แบ็กเอนด์ของแอปจะส่งคำตัดสินไปยังเซิร์ฟเวอร์ Google Play ทั้งนี้ Google เซิร์ฟเวอร์ Play จะถอดรหัสและยืนยันผลการตัดสิน และส่งคืนผลลัพธ์ไปยัง ของแบ็กเอนด์ของแอป
  6. แบ็กเอนด์ของแอปจะช่วยกำหนดวิธีดำเนินการต่อโดยพิจารณาจากสัญญาณที่มีอยู่ใน เพย์โหลดโทเค็น
  7. แบ็กเอนด์ของแอปจะส่งผลการตัดสินใจไปยังแอป

สร้าง Nonce

เมื่อปกป้องการดำเนินการในแอปด้วย Play Integrity API คุณจะทำสิ่งต่อไปนี้ได้ ใช้ประโยชน์จากฟิลด์ nonce เพื่อลดการโจมตีบางประเภท เช่น การโจมตีแบบ Person-in-the-middle (PITM) และการโจมตีแบบเล่นซ้ำ เดอะเพลย์ Integrity API จะแสดงค่าที่คุณกำหนดไว้ในช่องนี้ภายในฟิลด์ที่ลงนาม การตอบกลับด้านความสมบูรณ์

ค่าที่ตั้งไว้ในช่อง nonce ต้องมีรูปแบบที่ถูกต้อง:

  • String
  • ปลอดภัยสำหรับ URL
  • เข้ารหัสเป็น Base64 และไม่มีการรวม
  • ต้องมีอักขระอย่างน้อย 16 ตัว
  • มีอักขระได้สูงสุด 500 ตัว

ตัวอย่างวิธีทั่วไปในการใช้ช่อง nonce ใน Play มีดังนี้ Integrity API หากต้องการการปกป้องที่รัดกุมที่สุดจาก nonce คุณสามารถรวม วิธีการด้านล่าง

ใส่แฮชคำขอเพื่อป้องกันการปลอมแปลง

คุณสามารถใช้พารามิเตอร์ nonce ในคำขอ API แบบคลาสสิกได้ในลักษณะเดียวกับ requestHash ในคำขอ API มาตรฐานเพื่อปกป้องเนื้อหาของ คำขอเกี่ยวกับการปลอมแปลง

เมื่อคุณขอการตัดสินความสมบูรณ์:

  1. คำนวณไดเจสต์ของพารามิเตอร์คำขอที่สำคัญทั้งหมด (เช่น SHA256 ของพารามิเตอร์ คำขอการทำให้เป็นอนุกรม) จากการดำเนินการของผู้ใช้หรือคำขอของเซิร์ฟเวอร์ที่ ยังเกิดขึ้นอยู่
  2. ใช้ setNonce เพื่อตั้งค่าช่อง nonce เป็นค่าของไดเจสต์ที่คำนวณแล้ว

เมื่อคุณได้รับการตัดสินความสมบูรณ์:

  1. ถอดรหัสและตรวจสอบโทเค็นความสมบูรณ์ แล้วรับไดเจสต์จาก nonce
  2. คำนวณสรุปของคำขอในลักษณะเดียวกับในแอป (เช่น SHA256 ของการเรียงลำดับคำขอแบบคงที่)
  3. เปรียบเทียบไดเจสต์ฝั่งเซิร์ฟเวอร์และฝั่งเซิร์ฟเวอร์ หากไม่ตรงกัน ระบบจะ คำขอไม่น่าเชื่อถือ

ใส่ค่าที่ไม่ซ้ำกันเพื่อป้องกันการโจมตีแบบเล่นซ้ำ

เพื่อป้องกันไม่ให้ผู้ใช้ที่มีเจตนาร้ายใช้คำตอบก่อนหน้านี้จาก Play Integrity API คุณสามารถใช้ช่อง nonce เพื่อระบุแต่ละรายการโดยไม่ซ้ำกันได้

เมื่อคุณขอการตัดสินความสมบูรณ์:

  1. ได้รับค่าที่ไม่ซ้ำกันทั่วโลกในแบบที่ผู้ใช้ที่เป็นอันตรายไม่อาจคาดเดาได้ ตัวอย่างเช่น หมายเลขสุ่มเพื่อความปลอดภัยแบบเข้ารหัสลับที่สร้างขึ้นใน ฝั่งเซิร์ฟเวอร์อาจเป็นค่า หรือรหัสที่มีอยู่แล้ว เช่น เซสชัน หรือ รหัสธุรกรรม ตัวแปรที่ง่ายขึ้นและปลอดภัยน้อยลงคือการสร้างแบบสุ่ม หมายเลขในอุปกรณ์ เราขอแนะนำให้สร้างค่าที่ไม่ต่ำกว่า 128 บิต
  2. เรียกใช้ setNonce() เพื่อตั้งค่าช่อง nonce เป็นค่าที่ไม่ซ้ำจากขั้นตอนที่ 1

เมื่อคุณได้รับการตัดสินความสมบูรณ์:

  1. ถอดรหัสและยืนยันโทเค็นความสมบูรณ์ แล้วรับค่าที่ไม่ซ้ำกันจาก nonce
  2. หากมีการสร้างค่าจากขั้นตอนที่ 1 บนเซิร์ฟเวอร์ ให้ตรวจสอบว่าค่า ได้รับค่าที่ไม่ซ้ำเป็นหนึ่งในค่าที่สร้างขึ้น ที่ใช้เป็นครั้งแรก (เซิร์ฟเวอร์ของคุณจะต้องเก็บบันทึกของ สำหรับระยะเวลาที่เหมาะสม) หากใช้ค่าที่ไม่ซ้ำกันที่ได้รับ อยู่แล้วหรือไม่ปรากฏในระเบียน ปฏิเสธคำขอ
  3. ไม่เช่นนั้น หากมีการสร้างค่าที่ไม่ซ้ำกันในอุปกรณ์ ให้ตรวจสอบว่าค่า จะมีการใช้ค่าที่ได้รับเป็นครั้งแรก (เซิร์ฟเวอร์ของคุณจะต้อง บันทึกค่าที่เห็นแล้วในระยะเวลาที่เหมาะสม) หากฟิลด์ได้รับ มีการใช้ค่าที่ไม่ซ้ำกันแล้ว โปรดปฏิเสธคำขอ

รวมการป้องกันการโจมตีแบบสอดแทรกและการโจมตีซ้ำเข้าด้วยกัน (แนะนำ)

คุณสามารถใช้ฟิลด์ nonce เพื่อป้องกันทั้งการปลอมแปลงและ การโจมตีซ้ำไปพร้อมกัน โดยสร้างค่าที่ไม่ซ้ำกันเป็น ที่อธิบายไว้ข้างต้น และใส่ข้อมูลนี้เป็นส่วนหนึ่งของคำขอของคุณ จากนั้นคำนวณค่า แฮชคำขอ อย่าลืมใส่ค่าที่ไม่ซ้ำกันเป็นส่วนหนึ่งของแฮช CANNOT TRANSLATE ดังนี้

เมื่อคุณขอการตัดสินความสมบูรณ์:

  1. ผู้ใช้เป็นผู้เริ่มการดำเนินการที่มีมูลค่าสูง
  2. รับค่าที่ไม่ซ้ำกันสำหรับการกระทำนี้ตามที่อธิบายไว้ในคอลัมน์รวมที่ไม่ซ้ำ ค่าต่างๆ เพื่อป้องกันการโจมตีแบบเล่นซ้ำ
  3. เตรียมข้อความที่ต้องการปกป้อง ระบุค่าที่ไม่ซ้ำกันจากขั้นตอนที่ 2 ในข้อความ
  4. แอปของคุณจะคำนวณสรุปข้อความที่ต้องการปกป้อง เช่น ที่อธิบายไว้ในหัวข้อรวมแฮชคำขอเพื่อป้องกัน การงัดแงะ เนื่องจากข้อความจะมีแท็ก ค่าที่ไม่ซ้ำกันจะเป็นส่วนหนึ่งของแฮช
  5. ใช้ setNonce() เพื่อตั้งค่าช่อง nonce เป็นไดเจสต์ที่คำนวณจาก ขั้นตอนก่อนหน้า

เมื่อคุณได้รับการตัดสินความสมบูรณ์:

  1. รับค่าที่ไม่ซ้ำจากคำขอ
  2. ถอดรหัสและตรวจสอบโทเค็นความสมบูรณ์ แล้วรับไดเจสต์จาก nonce
  3. ตามที่อธิบายไว้ในส่วนรวมแฮชคำขอเพื่อป้องกันการปลอมแปลง ให้คำนวณไดเจสต์อีกครั้งทางฝั่งเซิร์ฟเวอร์ และตรวจสอบว่าตรงกับ ไดเจสต์ที่ได้จากโทเค็นความสมบูรณ์
  4. ตามที่อธิบายไว้ในส่วนรวมค่าที่ไม่ซ้ำกันเพื่อป้องกันไม่ให้มีการเล่นซ้ำ การโจมตี ให้ตรวจสอบความถูกต้องของค่าที่ไม่ซ้ำ

แผนภาพลำดับต่อไปนี้แสดงขั้นตอนเหล่านี้ในฝั่งเซิร์ฟเวอร์ nonce:

แผนภาพลำดับที่แสดงวิธีป้องกันการปลอมแปลงและเล่นซ้ำ
การโจมตี

ขอการตัดสินความสมบูรณ์

หลังจากสร้าง nonce คุณจะขอการตัดสินความสมบูรณ์จาก Google ได้ เล่น โดยทำตามขั้นตอนต่อไปนี้

  1. สร้าง IntegrityManager ดังที่แสดงในตัวอย่างต่อไปนี้
  2. สร้าง IntegrityTokenRequest โดยระบุ nonce ผ่านทาง setNonce() ในเครื่องมือสร้างที่เกี่ยวข้อง แอปที่เผยแพร่โดยเฉพาะ ภายนอก Google Play และ SDK ก็จะต้องระบุ หมายเลขโปรเจ็กต์ผ่านเมธอด setCloudProjectNumber() แอปใน Google Play จะลิงก์กับโปรเจ็กต์ที่อยู่ในระบบคลาวด์ใน Play Console และไม่จำเป็นต้อง กำหนดหมายเลขโปรเจ็กต์ที่อยู่ในระบบคลาวด์ในคำขอ
  3. ใช้ผู้จัดการเพื่อโทรหา requestIntegrityToken() โดยจัดเตรียม IntegrityTokenRequest

Kotlin

// Receive the nonce from the secure server.
val nonce: String = ...

// Create an instance of a manager.
val integrityManager =
    IntegrityManagerFactory.create(applicationContext)

// Request the integrity token by providing a nonce.
val integrityTokenResponse: Task<IntegrityTokenResponse> =
    integrityManager.requestIntegrityToken(
        IntegrityTokenRequest.builder()
             .setNonce(nonce)
             .build())

Java

import com.google.android.gms.tasks.Task; ...

// Receive the nonce from the secure server.
String nonce = ...

// Create an instance of a manager.
IntegrityManager integrityManager =
    IntegrityManagerFactory.create(getApplicationContext());

// Request the integrity token by providing a nonce.
Task<IntegrityTokenResponse> integrityTokenResponse =
    integrityManager
        .requestIntegrityToken(
            IntegrityTokenRequest.builder().setNonce(nonce).build());

เอกภาพ

IEnumerator RequestIntegrityTokenCoroutine() {
    // Receive the nonce from the secure server.
    var nonce = ...

    // Create an instance of a manager.
    var integrityManager = new IntegrityManager();

    // Request the integrity token by providing a nonce.
    var tokenRequest = new IntegrityTokenRequest(nonce);
    var requestIntegrityTokenOperation =
        integrityManager.RequestIntegrityToken(tokenRequest);

    // Wait for PlayAsyncOperation to complete.
    yield return requestIntegrityTokenOperation;

    // Check the resulting error code.
    if (requestIntegrityTokenOperation.Error != IntegrityErrorCode.NoError)
    {
        AppendStatusLog("IntegrityAsyncOperation failed with error: " +
                requestIntegrityTokenOperation.Error);
        yield break;
    }

    // Get the response.
    var tokenResponse = requestIntegrityTokenOperation.GetResult();
}

เนทีฟ

/// Create an IntegrityTokenRequest opaque object.
const char* nonce = RequestNonceFromServer();
IntegrityTokenRequest* request;
IntegrityTokenRequest_create(&request);
IntegrityTokenRequest_setNonce(request, nonce);

/// Prepare an IntegrityTokenResponse opaque type pointer and call
/// IntegerityManager_requestIntegrityToken().
IntegrityTokenResponse* response;
IntegrityErrorCode error_code =
        IntegrityManager_requestIntegrityToken(request, &response);

/// ...
/// Proceed to polling iff error_code == INTEGRITY_NO_ERROR
if (error_code != INTEGRITY_NO_ERROR)
{
    /// Remember to call the *_destroy() functions.
    return;
}
/// ...
/// Use polling to wait for the async operation to complete.
/// Note, the polling shouldn't block the thread where the IntegrityManager
/// is running.

IntegrityResponseStatus response_status;

/// Check for error codes.
IntegrityErrorCode error_code =
        IntegrityTokenResponse_getStatus(response, &response_status);
if (error_code == INTEGRITY_NO_ERROR
    && response_status == INTEGRITY_RESPONSE_COMPLETED)
{
    const char* integrity_token = IntegrityTokenResponse_getToken(response);
    SendTokenToServer(integrity_token);
}
/// ...
/// Remember to free up resources.
IntegrityTokenRequest_destroy(request);
IntegrityTokenResponse_destroy(response);
IntegrityManager_destroy();

ถอดรหัสและยืนยันผลการตัดสินความสมบูรณ์

เมื่อคุณขอการตัดสินความสมบูรณ์ Play Integrity API จะแสดงไฟล์ โทเค็นการตอบกลับ nonce ที่คุณระบุไว้ในคำขอจะกลายเป็นส่วนหนึ่งของ โทเค็นการตอบกลับ

รูปแบบโทเค็น

โทเค็นนี้เป็น JSON Web Token (JWT) ที่ฝังไว้ ซึ่ง คือ JSON Web Encryption (JWE) ของ JSON Web Signature (JWS) ส่วนประกอบ JWE และ JWS จะแสดงโดยใช้คอมแพ็คท์ การเรียงอันดับ ที่ใช้เวลาเพียง 2 นาที

รองรับอัลกอริทึมการเข้ารหัส / การลงนามใน JWT ต่างๆ การนำไปใช้งาน:

  • JWE ใช้ A256KW สำหรับ alg และ A256GCM สำหรับ enc

  • JWS ใช้ ES256

ถอดรหัสและยืนยันบนเซิร์ฟเวอร์ของ Google (แนะนำ)

Play Integrity API ช่วยให้คุณสามารถถอดรหัสและยืนยันผลการตัดสินความสมบูรณ์ใน เซิร์ฟเวอร์ของ Google ซึ่งช่วยเพิ่มความปลอดภัยให้กับแอปของคุณ โดยทำตามขั้นตอนต่อไปนี้ ขั้นตอน:

  1. สร้างบัญชีบริการ ในโปรเจ็กต์ Google Cloud ที่ลิงก์กับแอปของคุณ
  2. ในเซิร์ฟเวอร์ของแอป ให้ดึงข้อมูลโทเค็นเพื่อการเข้าถึงจากบัญชีบริการ ข้อมูลเข้าสู่ระบบโดยใช้ขอบเขต playintegrity และส่งคำขอต่อไปนี้

    playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \
    '{ "integrity_token": "INTEGRITY_TOKEN" }'
  3. อ่านการตอบสนอง JSON

ถอดรหัสและยืนยันในเครื่อง

หากเลือกจัดการและดาวน์โหลดคีย์การเข้ารหัสการตอบกลับ คุณจะทำสิ่งต่อไปนี้ได้ ถอดรหัสและยืนยันโทเค็นที่แสดงผลภายในสภาพแวดล้อมเซิร์ฟเวอร์ที่ปลอดภัยของคุณเอง คุณสามารถรับโทเค็นที่ส่งคืนได้โดยใช้ IntegrityTokenResponse#token()

ตัวอย่างต่อไปนี้แสดงวิธีถอดรหัสคีย์ AES และคีย์สาธารณะที่เข้ารหัส DER คีย์ EC สำหรับการยืนยันลายเซ็นจาก Play Console เป็นตามภาษา (ในกรณีของเรา) คีย์ (ภาษาโปรแกรม Java) ในแบ็กเอนด์ของแอป หมายเหตุ ว่าคีย์มีการเข้ารหัส base64 โดยใช้แฟล็กเริ่มต้น

Kotlin

// base64OfEncodedDecryptionKey is provided through Play Console.
var decryptionKeyBytes: ByteArray =
    Base64.decode(base64OfEncodedDecryptionKey, Base64.DEFAULT)

// Deserialized encryption (symmetric) key.
var decryptionKey: SecretKey = SecretKeySpec(
    decryptionKeyBytes,
    /* offset= */ 0,
    AES_KEY_SIZE_BYTES,
    AES_KEY_TYPE
)

// base64OfEncodedVerificationKey is provided through Play Console.
var encodedVerificationKey: ByteArray =
    Base64.decode(base64OfEncodedVerificationKey, Base64.DEFAULT)

// Deserialized verification (public) key.
var verificationKey: PublicKey = KeyFactory.getInstance(EC_KEY_TYPE)
    .generatePublic(X509EncodedKeySpec(encodedVerificationKey))

Java

// base64OfEncodedDecryptionKey is provided through Play Console.
byte[] decryptionKeyBytes =
    Base64.decode(base64OfEncodedDecryptionKey, Base64.DEFAULT);

// Deserialized encryption (symmetric) key.
SecretKey decryptionKey =
    new SecretKeySpec(
        decryptionKeyBytes,
        /* offset= */ 0,
        AES_KEY_SIZE_BYTES,
        AES_KEY_TYPE);

// base64OfEncodedVerificationKey is provided through Play Console.
byte[] encodedVerificationKey =
    Base64.decode(base64OfEncodedVerificationKey, Base64.DEFAULT);
// Deserialized verification (public) key.
PublicKey verificationKey =
    KeyFactory.getInstance(EC_KEY_TYPE)
        .generatePublic(new X509EncodedKeySpec(encodedVerificationKey));

ถัดไป ให้ใช้คีย์เหล่านี้เพื่อถอดรหัสโทเค็นความสมบูรณ์ (ส่วน JWE) จากนั้น ตรวจสอบและแยกส่วน JWS ที่ฝังอยู่

Kotlin

val jwe: JsonWebEncryption =
    JsonWebStructure.fromCompactSerialization(integrityToken) as JsonWebEncryption
jwe.setKey(decryptionKey)

// This also decrypts the JWE token.
val compactJws: String = jwe.getPayload()

val jws: JsonWebSignature =
    JsonWebStructure.fromCompactSerialization(compactJws) as JsonWebSignature
jws.setKey(verificationKey)

// This also verifies the signature.
val payload: String = jws.getPayload()

Java

JsonWebEncryption jwe =
    (JsonWebEncryption)JsonWebStructure
        .fromCompactSerialization(integrityToken);
jwe.setKey(decryptionKey);

// This also decrypts the JWE token.
String compactJws = jwe.getPayload();

JsonWebSignature jws =
    (JsonWebSignature) JsonWebStructure.fromCompactSerialization(compactJws);
jws.setKey(verificationKey);

// This also verifies the signature.
String payload = jws.getPayload();

เพย์โหลดที่ได้คือโทเค็นข้อความธรรมดาที่มีความสมบูรณ์ คำตัดสิน