เอกสารนี้อธิบายวิธีที่นักพัฒนาแอปสามารถใช้ฟีเจอร์ความปลอดภัยที่ Android มีให้เพื่อกำหนดสิทธิ์ของตนเอง การกำหนดสิทธิ์ที่กำหนดเองจะช่วยให้แอปแชร์ทรัพยากรและความสามารถกับแอปอื่นๆ ได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับสิทธิ์ได้ที่ภาพรวมของสิทธิ์
ฉากหลัง
Android เป็นระบบปฏิบัติการที่แยกสิทธิ์ โดยแต่ละแอปจะทำงานด้วยข้อมูลประจำตัวของระบบที่แตกต่างกัน (รหัสผู้ใช้ Linux และรหัสกลุ่ม) นอกจากนี้ ส่วนต่างๆ ของระบบยังแยกออกเป็นข้อมูลประจำตัวที่แตกต่างกันด้วย Linux จึงแยกแอปออกจากกันและออกจากระบบ
แอปสามารถแสดงฟังก์ชันการทำงานของตนต่อแอปอื่นๆ ได้โดยการกำหนดสิทธิ์ที่แอปอื่นๆ สามารถขอได้ นอกจากนี้ยังกำหนดสิทธิ์ที่แอปอื่นๆ ที่ลงชื่อด้วยใบรับรองเดียวกันจะได้รับโดยอัตโนมัติได้ด้วย
การลงนามแอป
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> ไม่ได้ระบุสิทธิ์ที่เป็นของกลุ่ม แต่จะตั้งชื่อให้กลุ่ม
คุณสามารถวางสิทธิ์ในกลุ่มได้โดยกำหนดชื่อกลุ่มให้กับแอตทริบิวต์ permissionGroup ขององค์ประกอบ <permission>
องค์ประกอบ <permission-tree> จะประกาศเนมสเปซสำหรับกลุ่มสิทธิ์ที่กำหนดไว้ในโค้ด
คำแนะนำสิทธิ์ที่กำหนดเอง
คุณสามารถกำหนดสิทธิ์ที่กำหนดเองสำหรับแอปและขอสิทธิ์ที่กำหนดเองจากแอปอื่นๆ ได้โดยกำหนดองค์ประกอบ <uses-permission>
อย่างไรก็ตาม โปรดประเมินอย่างรอบคอบว่าจำเป็นต้องดำเนินการดังกล่าวหรือไม่
- หากคุณกำลังออกแบบชุดแอปที่แสดงฟังก์ชันการทำงานซึ่งกันและกัน ให้ลองออกแบบแอปเพื่อให้มีการกำหนดสิทธิ์แต่ละรายการเพียงครั้งเดียว คุณต้องดำเนินการนี้หากแอปทั้งหมดไม่ได้ลงนามด้วยใบรับรองเดียวกัน แม้ว่าแอปทั้งหมดจะลงนามด้วยใบรับรองเดียวกัน แต่แนวทางปฏิบัติแนะนำคือให้กำหนดสิทธิ์แต่ละรายการเพียงครั้งเดียว
- หากฟังก์ชันการทำงานใช้ได้เฉพาะกับแอปที่ลงนามด้วย App Signing เดียวกับแอปที่ให้บริการ คุณอาจหลีกเลี่ยงการกำหนดสิทธิ์ที่กำหนดเองได้โดยใช้การตรวจสอบลายเซ็น เมื่อแอปหนึ่งของคุณส่งคำขอไปยังอีกแอปหนึ่งของคุณ แอปที่ 2 จะยืนยันได้ว่าแอปทั้งสองได้รับการรับรองด้วยใบรับรองเดียวกันก่อนที่จะปฏิบัติตามคำขอ
หากจำเป็นต้องใช้สิทธิ์ที่กำหนดเอง ให้พิจารณาว่าเฉพาะแอปพลิเคชันที่ลงนามโดยนักพัฒนาแอปรายเดียวกับแอปพลิเคชันที่ทำการตรวจสอบสิทธิ์เท่านั้นที่จำเป็นต้องเข้าถึงหรือไม่ เช่น เมื่อใช้การสื่อสารระหว่างโปรเซสที่ปลอดภัยระหว่างแอปพลิเคชัน 2 รายการจากนักพัฒนาแอปรายเดียวกัน หากเป็นเช่นนั้น เราขอแนะนำให้ใช้สิทธิ์ลายเซ็น สิทธิ์ลายเซ็นมีความโปร่งใสต่อผู้ใช้และหลีกเลี่ยงสิทธิ์ที่ผู้ใช้ยืนยัน ซึ่งอาจทำให้ผู้ใช้สับสน
อ่านต่อเกี่ยวกับหัวข้อต่อไปนี้
<uses-permission>- เอกสารอ้างอิง API สำหรับแท็กไฟล์ Manifest ที่ประกาศสิทธิ์ของระบบที่แอปของคุณต้องใช้
คุณอาจสนใจสิ่งต่อไปนี้ด้วย
- ภาพรวมความปลอดภัยของ Android
- การพูดคุยอย่างละเอียดเกี่ยวกับโมเดลความปลอดภัยของแพลตฟอร์ม Android