กำหนดสิทธิ์ของแอปที่กำหนดเอง

เอกสารนี้อธิบายวิธีที่นักพัฒนาแอปสามารถใช้ ฟีเจอร์ความปลอดภัยที่ Android มีให้เพื่อกำหนดสิทธิ์ของตนเอง โดยการกำหนดสิทธิ์ที่กำหนดเอง แอปจะแชร์ทรัพยากรและความสามารถกับแอปอื่นๆ ได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับสิทธิ์ได้ที่ภาพรวมสิทธิ์

ฉากหลัง

Android เป็นระบบปฏิบัติการที่มีการแยกสิทธิ์ ซึ่งแต่ละ แอปจะทำงานด้วยข้อมูลประจำตัวของระบบที่แตกต่างกัน (รหัสผู้ใช้และรหัสกลุ่ม Linux) นอกจากนี้ ระบบยังแยกส่วนต่างๆ ออกเป็นข้อมูลประจำตัวที่แตกต่างกันด้วย ด้วยเหตุนี้ Linux จึงแยกแอปออกจากกันและแยกแอปออกจากระบบ

แอปสามารถเปิดเผยฟังก์ชันการทำงานของตนเองให้แอปอื่นๆ ได้โดยการกำหนดสิทธิ์ ที่แอปอื่นๆ สามารถขอได้ นอกจากนี้ยังกำหนดสิทธิ์ที่ พร้อมใช้งานโดยอัตโนมัติสำหรับแอปอื่นๆ ที่ลงนามด้วย ใบรับรองเดียวกันได้ด้วย

App Signing

APK ทั้งหมดต้องลงนามด้วยใบรับรอง ที่นักพัฒนาแอปเป็นผู้เก็บคีย์ส่วนตัว โดยใบรับรอง ไม่ จำเป็นต้องลงนามโดยผู้ออกใบรับรอง แอป Android สามารถใช้ใบรับรองแบบ Self-signed ได้ ซึ่งเป็นเรื่อง ปกติ จุดประสงค์ของ ใบรับรองใน Android คือเพื่อแยกแยะผู้เขียนแอป ซึ่งจะช่วยให้ระบบให้หรือปฏิเสธการเข้าถึงสิทธิ์ระดับลายเซ็นของแอป และให้หรือปฏิเสธคำขอของแอปที่จะได้รับข้อมูลประจำตัว Linux เดียวกับแอปอื่น

ให้สิทธิ์ลายเซ็นหลังจากเวลาผลิตอุปกรณ์

ตั้งแต่ Android 12 (ระดับ API 31) เป็นต้นไป แอตทริบิวต์ knownCerts สำหรับสิทธิ์ระดับลายเซ็นจะช่วยให้คุณอ้างอิงถึงค่าแฮชของใบรับรองการลงนามที่ทราบได้ในเวลาประกาศ

คุณสามารถประกาศแอตทริบิวต์ knownCerts และใช้แฟล็ก knownSigner ในแอตทริบิวต์ protectionLevel ของแอป สำหรับสิทธิ์ระดับลายเซ็นที่เฉพาะเจาะจง จากนั้นระบบจะให้สิทธิ์ดังกล่าวแก่แอปที่ขอ หากผู้ลงนามใดๆ ในลำดับการลงนามของแอปที่ขอ ซึ่งรวมถึงผู้ลงนามปัจจุบัน ตรงกับค่าแฮชรายการใดรายการหนึ่งที่ประกาศไว้พร้อมกับสิทธิ์ในแอตทริบิวต์ knownCerts

แฟล็ก knownSigner ช่วยให้อุปกรณ์และแอปให้สิทธิ์ลายเซ็นแก่แอปอื่นๆ ได้โดยไม่ต้องลงนามแอปในเวลาที่ผลิตและจัดส่งอุปกรณ์

รหัสผู้ใช้และการเข้าถึงไฟล์

เมื่อติดตั้ง Android จะกำหนดรหัสผู้ใช้ Linux ที่แตกต่างกันให้กับแต่ละแพ็กเกจ ข้อมูลประจำตัวจะคงที่ตลอดอายุการใช้งานของแพ็กเกจในอุปกรณ์นั้น ในอุปกรณ์อื่น แพ็กเกจเดียวกันอาจมี UID ที่แตกต่างกัน สิ่งสำคัญคือแต่ละแพ็กเกจต้องมี UID ที่แตกต่างกันในอุปกรณ์ที่กำหนด

เนื่องจากการบังคับใช้การรักษาความปลอดภัยเกิดขึ้นที่ระดับกระบวนการ โดยปกติแล้วโค้ดของแพ็กเกจ 2 รายการจึงไม่สามารถทำงานในกระบวนการเดียวกันได้ เนื่องจากต้องทำงานในฐานะผู้ใช้ Linux ที่แตกต่างกัน

ระบบจะกำหนดรหัสผู้ใช้ของแอปให้กับข้อมูลที่แอปจัดเก็บไว้ และโดยปกติแล้วแพ็กเกจอื่นๆ จะเข้าถึงข้อมูลดังกล่าวไม่ได้

ดูข้อมูลเพิ่มเติมเกี่ยวกับโมเดลความปลอดภัยของ Android ได้ที่ ภาพรวมความปลอดภัยของ Android

กำหนดและบังคับใช้สิทธิ์

หากต้องการบังคับใช้สิทธิ์ของคุณเอง คุณต้องประกาศสิทธิ์เหล่านั้นใน AndroidManifest.xml ก่อนโดยใช้องค์ประกอบ <permission> อย่างน้อย 1 รายการ

รูปแบบการตั้งชื่อ

ระบบไม่อนุญาตให้แพ็กเกจหลายรายการประกาศสิทธิ์ที่มีชื่อเดียวกัน เว้นแต่ว่าแพ็กเกจทั้งหมดจะลงนามด้วยใบรับรองเดียวกัน หากแพ็กเกจประกาศสิทธิ์ ระบบจะไม่อนุญาตให้ผู้ใช้ติดตั้งแพ็กเกจอื่นๆ ที่มีชื่อสิทธิ์เดียวกัน เว้นแต่ว่าแพ็กเกจเหล่านั้นจะลงนามด้วยใบรับรองเดียวกันกับแพ็กเกจแรก

เราขอแนะนำให้ใส่คำนำหน้าสิทธิ์ด้วยชื่อแพ็กเกจของแอป โดยใช้การตั้งชื่อแบบย้อนโดเมน ตามด้วย .permission. แล้วตามด้วยคำอธิบายความสามารถที่สิทธิ์นั้นแสดงถึงในรูปแบบ SNAKE_CASE ตัวพิมพ์ใหญ่ เช่น com.example.myapp.permission.ENGAGE_HYPERSPACE

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

ตัวอย่าง

เช่น แอปที่ต้องการควบคุมแอปอื่นๆ ที่สามารถเริ่มกิจกรรมอย่างใดอย่างหนึ่งของตนเองได้สามารถประกาศสิทธิ์สำหรับการดำเนินการนี้ได้ดังนี้

<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.example.myapp" >
    
    <permission
      android:name="com.example.myapp.permission.DEADLY_ACTIVITY"
      android:label="@string/permlab_deadlyActivity"
      android:description="@string/permdesc_deadlyActivity"
      android:permissionGroup="android.permission-group.COST_MONEY"
      android:protectionLevel="dangerous" />
    ...
</manifest>

แอตทริบิวต์ protectionLevel เป็นแอตทริบิวต์ที่จำเป็นและจะบอกระบบว่าจะ แจ้งให้ผู้ใช้ทราบเกี่ยวกับแอปที่ต้องใช้สิทธิ์หรือแอปที่สามารถ มีสิทธิ์ได้อย่างไร ดังที่อธิบายไว้ในเอกสารประกอบที่ลิงก์

แอตทริบิวต์ android:permissionGroup เป็นแอตทริบิวต์ที่ไม่บังคับและใช้เพื่อช่วยให้ระบบแสดงสิทธิ์ แก่ผู้ใช้เท่านั้น ในกรณีส่วนใหญ่ คุณจะตั้งค่านี้เป็นกลุ่มระบบมาตรฐาน (ระบุไว้ใน android.Manifest.permission_group) แม้ว่าคุณจะกำหนดกลุ่มด้วยตนเองได้ดังที่อธิบายไว้ในส่วนต่อไปนี้ เราขอแนะนำให้ใช้กลุ่มที่มีอยู่ เนื่องจากจะช่วยลดความซับซ้อนของ UI สิทธิ์ที่แสดงต่อผู้ใช้

คุณต้องระบุทั้งป้ายกำกับและคำอธิบายสำหรับสิทธิ์ ซึ่งเป็นทรัพยากรสตริงที่ผู้ใช้จะเห็นเมื่อ ดูรายการสิทธิ์ (android:label) หรือรายละเอียดเกี่ยวกับสิทธิ์รายการเดียว (android:description) ป้ายกำกับควรสั้นๆ โดยมีคำไม่กี่คำที่อธิบายฟังก์ชันการทำงานหลักที่สิทธิ์นั้นปกป้อง ส่วนคำอธิบายควรมี 2-3 ประโยคที่อธิบายสิ่งที่ผู้มีสิทธิ์ทำได้ รูปแบบที่เราใช้คือคำอธิบาย 2 ประโยค โดยประโยคแรกอธิบายสิทธิ์และประโยคที่ 2 เตือนผู้ใช้เกี่ยวกับสิ่งต่างๆ ที่อาจเกิดขึ้นหากแอปได้รับสิทธิ์

ตัวอย่างป้ายกำกับและคำอธิบายสำหรับสิทธิ์ CALL_PHONE

<string name="permlab_callPhone">directly call phone numbers</string>
<string name="permdesc_callPhone">Allows the app to call non-emergency
phone numbers without your intervention. Malicious apps may cause unexpected
calls on your phone bill.</string>

สร้างกลุ่มสิทธิ์

ดังที่แสดงในส่วนก่อนหน้า คุณสามารถใช้ android:permissionGroup แอตทริบิวต์เพื่อช่วยให้ระบบอธิบาย สิทธิ์แก่ผู้ใช้ได้ ในกรณีส่วนใหญ่ คุณจะตั้งค่านี้เป็นกลุ่มระบบมาตรฐาน (ระบุไว้ใน android.Manifest.permission_group) แต่คุณยังกำหนดกลุ่มของคุณเองด้วย <permission-group>ได้ด้วย

องค์ประกอบ <permission-group> จะกำหนดป้ายกำกับสำหรับชุด สิทธิ์ ทั้งสิทธิ์ที่ประกาศไว้ในไฟล์ Manifest ด้วย <permission> องค์ประกอบ และสิทธิ์ที่ประกาศไว้ที่อื่น ซึ่งจะส่งผลต่อวิธีจัดกลุ่มสิทธิ์เมื่อแสดงต่อผู้ใช้เท่านั้น องค์ประกอบ <permission-group> ไม่ได้ระบุสิทธิ์ที่เป็นของกลุ่ม แต่ จะกำหนดชื่อให้กับกลุ่ม

คุณสามารถวางสิทธิ์ไว้ในกลุ่มได้โดยการกำหนดชื่อกลุ่มให้กับ <permission> แอตทริบิวต์ permissionGroup ขององค์ประกอบ

องค์ประกอบ <permission-tree> จะประกาศเนมสเปซสำหรับกลุ่มสิทธิ์ที่กำหนดไว้ใน โค้ด

คำแนะนำเกี่ยวกับสิทธิ์ที่กำหนดเอง

คุณสามารถกำหนดสิทธิ์ที่กำหนดเองสำหรับแอปและขอสิทธิ์ที่กำหนดเอง จากแอปอื่นๆ ได้โดยการกำหนด <uses-permission> องค์ประกอบ อย่างไรก็ตาม ให้ประเมินอย่างรอบคอบว่าจำเป็นต้องดำเนินการดังกล่าวหรือไม่

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

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

อ่านเพิ่มเติมเกี่ยวกับ

<uses-permission>
การอ้างอิง API สำหรับแท็กไฟล์ Manifest ที่ประกาศสิทธิ์ของระบบที่แอปต้องใช้

คุณอาจสนใจหัวข้อต่อไปนี้ด้วย

ภาพรวมความปลอดภัยของ Android
การอภิปรายโดยละเอียดเกี่ยวกับโมเดลความปลอดภัยของแพลตฟอร์ม Android