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

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

ฉากหลัง

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

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

การลงนามแอป

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

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

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

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

Flag 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 ประโยคที่อธิบายสิ่งที่สิทธิ์นั้นอนุญาตให้ผู้ถือสิทธิ์ทําได้ รูปแบบของเราคือคําอธิบาย 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