Xác định quyền tuỳ chỉnh dành cho ứng dụng

Tài liệu này nhằm hướng dẫn nhà phát triển ứng dụng sử dụng các tính năng bảo mật do Android cung cấp để xác định quyền của họ. Nhờ việc xác định quyền tuỳ chỉnh, một ứng dụng có thể chia sẻ tài nguyên và khả năng của ứng dụng đó với các ứng dụng khác. Để biết thêm thông tin về các quyền, hãy xem bài viết Tổng quan về quyền.

Thông tin khái quát

Android là một hệ điều hành phân tách bằng đặc quyền, trong đó mỗi ứng dụng chạy với một danh tính hệ thống riêng biệt (mã nhận dạng người dùng Linux và mã nhóm). Các phần của hệ thống cũng được phân tách thành danh tính riêng biệt. Do đó, Linux sẽ tách riêng các ứng dụng với nhau và tách khỏi hệ thống.

Ứng dụng có thể báo chức năng của mình cho ứng dụng khác bằng cách xác định các quyền mà ứng dụng khác có thể yêu cầu. Chúng cũng có thể xác định quyền được cung cấp tự động cho mọi ứng dụng khác được ký bằng cùng một chứng chỉ.

Ký ứng dụng

Tất cả tệp APK đều phải được ký bằng chứng chỉ do nhà phát triển ứng dụng nắm giữ khoá riêng tư. Chứng chỉ không cần phải do một tổ chức phát hành chứng chỉ ký. Ứng dụng Android được phép và thường sử dụng chứng chỉ tự ký. Mục đích của chứng chỉ trong Android là để phân biệt tác giả ứng dụng. Việc này cho phép hệ thống cấp hoặc từ chối ứng dụng tiếp cận quyền ở cấp chữ ký và cấp hoặc từ chối yêu cầu của ứng dụng để được trao cùng một danh tính Linux như ứng dụng khác.

Cấp quyền ký chữ ký sau thời gian sản xuất thiết bị

Kể từ Android 12 (API cấp 31), thuộc tính knownCerts đối với quyền ở cấp chữ ký cho phép bạn tham khảo thông báo về các chứng chỉ ký đã biết tại thời điểm khai báo.

Bạn có thể khai báo thuộc tính knownCerts và sử dụng cờ knownSigner trong thuộc tính protectionLevel của ứng dụng đối với một quyền cụ thể ở cấp chữ ký. Sau đó, hệ thống sẽ cấp quyền đó cho ứng dụng yêu cầu nếu bất kỳ người ký nào ở loạt ký của ứng dụng yêu cầu, kể cả người ký hiện tại, khớp với một trong các thông báo được khai báo bằng quyền trong thuộc tínhknownCerts.

Cờ knownSigner cho phép thiết bị và ứng dụng cấp quyền chữ ký cho ứng dụng khác mà không cần phải ký ứng dụng tại thời điểm sản xuất và vận chuyển thiết bị.

Quyền truy cập vào Mã nhận dạng người dùng và tệp

Tại thời điểm cài đặt, Android cung cấp cho mỗi gói một mã nhận dạng người dùng Linux riêng biệt. Danh tính gói sẽ không thay đổi trong suốt thời gian sử dụng trên thiết bị đó. Trên một thiết bị khác, gói đó có thể có một mã nhận dạng người dùng (UID) khác. Điều quan trọng là mỗi gói đều có một UID riêng biệt trên một thiết bị nhất định.

Do việc thực thi bảo mật xảy ra ở cấp quy trình, thường thì mã của hai gói bất kỳ không thể chạy trong cùng một quy trình vì các gói này cần chạy dưới dạng nhiều người dùng Linux khác nhau.

Mọi dữ liệu do một ứng dụng lưu trữ sẽ được gán mã nhận dạng người dùng của ứng dụng đó và thường thì các gói khác không thể truy cập vào dữ liệu đó.

Để biết thêm thông tin về mô hình bảo mật của Android, hãy xem bài viết Tổng quan về vấn đề bảo mật của Android

Định nghĩa và thực thi quyền

Để thực thi các quyền của mình, trước tiên phải khai báo các quyền đó trong AndroidManifest.xml bằng một hoặc nhiều phần tử <permission>.

Quy ước đặt tên

Hệ thống không cho phép nhiều gói khai báo một quyền có cùng tên, trừ trường hợp tất cả các gói đều được ký bằng cùng một chứng chỉ. Nếu một gói khai báo quyền, hệ thống cũng không cho phép người dùng cài đặt các gói khác có cùng tên quyền, trừ khi các gói đó được ký bằng cùng một chứng chỉ như với gói đầu tiên.

Bạn nên đặt tiền tố cho quyền với tên gói của một ứng dụng bằng cách đặt tên theo kiểu đảo ngược miền, tiếp theo là .permission. rồi mô tả chức năng mà quyền đó đại diện bằng chữ in hoa dạng SNAKE_CASE. Ví dụ: com.example.myapp.permission.ENGAGE_HYPERSPACE.

Việc làm theo đề xuất này giúp tránh đặt trùng tên và giúp xác định rõ ràng chủ sở hữu cũng như ý định của một quyền tuỳ chỉnh.

Ví dụ

Ví dụ: một ứng dụng cần kiểm soát việc ứng dụng nào khác có thể bắt đầu một trong các hoạt động của nó có thể khai báo quyền cho thao tác này như sau:

<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>

Thuộc tính protectionLevel là bắt buộc và cho hệ thống biết cách để thông báo cho người dùng về các ứng dụng đang yêu cầu cấp quyền hoặc ứng dụng nào có thể giữ quyền, như được mô tả trong tài liệu liên kết.

Thuộc tính android:permissionGroup là tuỳ chọn và chỉ được dùng để giúp hệ thống cho người dùng thấy quyền. Trong hầu hết trường hợp, hãy đặt thuộc tính này thành một nhóm hệ thống tiêu chuẩn (liệt kê trong android.Manifest.permission_group), mặc dù bạn có thể tự xác định một nhóm như được mô tả trong phần sau. Nên sử dụng một nhóm hiện có, vì điều này giúp đơn giản hoá giao diện người dùng quyền mà người dùng nhìn thấy.

Bạn cần phải cung cấp cả nhãn và nội dung mô tả cho quyền. Đây là tài nguyên chuỗi mà người dùng có thể thấy khi xem danh sách các quyền (android:label) hoặc các chi tiết về một quyền duy nhất (android:description). Nhãn phải ngắn gọn: một vài từ mô tả phần chức năng chính mà quyền đang bảo vệ. Phần mô tả là một vài câu mô tả những gì quyền cho phép chủ sở hữu làm. Quy ước của chúng tôi là hai câu: câu đầu tiên mô tả quyền, câu thứ hai cảnh báo người dùng về những kiểu bất trắc có thể xảy ra nếu một ứng dụng được cấp quyền.

Sau đây là ví dụ về một nhãn và nội dung mô tả quyền 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>

Tạo một nhóm quyền

Như đã trình bày ở phần trước, bạn có thể sử dụng thuộc tính android:permissionGroup để giúp hệ thống mô tả quyền cho người dùng. Trong hầu hết trường hợp, bạn đặt thuộc tính này cho một nhóm hệ thống tiêu chuẩn (được liệt kê trong android.Manifest.permission_group), nhưng bạn cũng có thể xác định nhóm của riêng mình bằng <permission-group>.

Phần tử <permission-group> xác định nhãn cho một nhóm quyền – cả những quyền đã được khai báo trong tệp kê khai với phần tử <permission> và những quyền được khai báo ở nơi khác. Việc này chỉ ảnh hưởng đến cách nhóm các quyền khi xuất hiện trước người dùng. Phần tử <permission-group> không chỉ định các quyền thuộc về nhóm, nhưng nó sẽ đặt tên cho nhóm.

Có thể đặt một quyền vào nhóm đó bằng cách gán tên nhóm cho thuộc tính permissionGroup của phần tử <permission>.

Phần tử <permission-tree> khai báo không gian tên cho một nhóm các quyền được xác định trong mã.

Đề xuất về quyền tuỳ chỉnh

Bạn có thể xác định quyền tuỳ chỉnh cho các ứng dụng của mình và yêu cầu quyền tuỳ chỉnh từ ứng dụng khác bằng cách xác định phần tử <uses-permission>. Tuy nhiên, hãy đánh giá kỹ lưỡng xem liệu việc đó có cần thiết hay không.

  • Nếu bạn đang thiết kế một bộ ứng dụng cho thấy chức năng lẫn cho nhau, hãy cố gắng thiết kế ứng dụng sao cho mỗi quyền chỉ được xác định một lần. Điều này là bắt buộc nếu tất cả ứng dụng đều không được ký bằng cùng một chứng chỉ. Ngay cả khi tất cả ứng dụng đều được ký bằng cùng một chứng chỉ, bạn vẫn nên xác định mỗi quyền chỉ một lần.
  • Nếu chức năng chỉ dành cho những ứng dụng được ký bằng chữ ký giống như ứng dụng cung cấp, bạn có thể tránh được việc xác định quyền tuỳ chỉnh bằng cách sử dụng tính năng kiểm tra chữ ký. Khi một trong những ứng dụng của bạn đưa ra yêu cầu với ứng dụng khác, ứng dụng thứ hai có thể xác minh rằng cả hai ứng dụng đều được ký với cùng một chứng chỉ trước khi tuân thủ yêu cầu đó.

Nếu quyền tuỳ chỉnh là cần thiết, hãy cân nhắc xem liệu chỉ các ứng dụng do cùng một nhà phát triển ký khi ứng dụng thực hiện việc kiểm tra quyền có cần truy cập quyền đó hay không, chẳng hạn như khi triển khai giao tiếp liên quy trình bảo mật giữa hai ứng dụng của cùng một nhà phát triển. Nếu vậy, bạn nên sử dụng quyền chữ ký. Quyền chữ ký có tính minh bạch trước người dùng và tránh những quyền cần người dùng xác nhận, do có thể khiến người dùng nhầm lẫn.

Tiếp tục đọc về:

<uses-permission>
Tài liệu tham khảo API cho thẻ tệp kê khai sẽ khai báo quyền hệ thống bắt buộc của ứng dụng.

Có thể bạn cũng quan tâm đến:

Tổng quan về tính bảo mật của Android
Thảo luận chi tiết về mô hình bảo mật của nền tảng Android.