เอกสารนี้อธิบายวิธีที่นักพัฒนาแอปสามารถใช้ฟีเจอร์ด้านความปลอดภัยที่ 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