查看: 179|回复: 0

鸿蒙 ASCF has.authorize 授权配置与拒绝处理

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在鸿蒙元服务开发中,ASCF 把权限申请收口到一个方法:has.authorize。无论是访问位置、通讯录、日历等用户数据,还是调用相机、麦克风、蓝牙等系统能力,都要先拿到用户授权。它看起来简单,但 scope 怎么配、module.json5 怎么声明、用户拒绝后怎么办,实际开发中很容易踩坑。下面按基本调用、权限声明、scope 对照、典型场景和排障点梳理。

一、has.authorize 基本调用
has.authorize 只有一个方法入口,scope 必填,用于指定申请的权限类型。如果用户之前已经同意过授权,不会再弹窗,直接走 success。
  1. has.authorize({
  2. scope: 'scope.userLocation',
  3. success: () => {
  4. console.info('用户已授权');
  5. },
  6. fail: (err) => {
  7. console.error('授权失败:', err);
  8. }
  9. });
复制代码

二、权限配置三步走
第一步,在 module.json5 的 requestPermissions 中声明系统权限,例如 CAMERA、MICROPHONE、LOCATION、APPROXIMATELY_LOCATION。不声明就调用 authorize,会直接走 fail。
第二步,在代码里通过 has.authorize 请求授权:
  1. has.authorize({
  2. scope: 'scope.camera',
  3. success: () => { /* 权限已拿到 */ },
  4. fail: (err) => { /* 被拒绝或未声明 */ }
  5. });
复制代码
第三步,处理失败情况。用户可能拒绝授权,拒绝后再次调用 has.authorize,可能不再弹窗,直接走 fail。

三、scope 与系统权限对照
位置:scope.userLocation 对应精确定位,需要 LOCATION 和 APPROXIMATELY_LOCATION 两个权限;scope.userFuzzyLocation 对应模糊定位,只需要 APPROXIMATELY_LOCATION。
设备:scope.camera 用于相机;scope.record 用于录音,录像需要同时具备 camera 和 record 权限。
联系人:scope.contact。
日历:scope.calendar。
蓝牙:scope.bluetooth。
通知:scope.notification。
这里要注意,一个 scope 可能对应多个系统权限,漏声明一个都会失败。

四、先授权再调用是常见模式
几乎所有需要权限的 API,都要先 authorize 再调用。直接调用业务 API,没授权时可能直接失败;正确做法是先申请对应 scope,再在 success 回调里调用业务 API。项目里蓝牙、通讯录、日历、WiFi 都遵循这个顺序。
  1. // 蓝牙
  2. has.authorize({
  3. scope: 'scope.bluetooth',
  4. success: () => {
  5. has.openBluetoothAdapter({ ... });
  6. }
  7. });
  8. // 通讯录
  9. has.authorize({
  10. scope: 'scope.contact',
  11. success: () => {
  12. has.addPhoneContact({ ... });
  13. }
  14. });
  15. // 日历
  16. has.authorize({
  17. scope: 'scope.calendar',
  18. success: () => {
  19. has.addPhoneCalendar({ ... });
  20. }
  21. });
  22. // WiFi:获取列表需要定位权限
  23. has.authorize({
  24. scope: 'scope.userLocation',
  25. success: () => {
  26. has.getWifiList({ ... });
  27. }
  28. });
复制代码
其中 WiFi 获取列表需要 scope.userLocation 权限,因为 WiFi 信息可用于定位,这一点比较反直觉。

五、用 Promise 封装授权
每次都写 success/fail 回调比较繁琐,可以封装成 Promise:
  1. function authorize(scope) {
  2. return new Promise((resolve, reject) => {
  3. has.authorize({
  4. scope: scope,
  5. success: () => resolve(),
  6. fail: (err) => reject(err)
  7. });
  8. });
  9. }
  10. async function getLocation() {
  11. try {
  12. await authorize('scope.userLocation');
  13. const location = await new Promise((resolve, reject) => {
  14. has.getLocation({
  15. success: (res) => resolve(res),
  16. fail: (err) => reject(err)
  17. });
  18. });
  19. console.info('位置:', location);
  20. } catch (err) {
  21. console.error('获取位置失败:', err);
  22. }
  23. }
复制代码

六、典型场景
场景一,一次性申请多个权限。某些功能需要多个权限,比如录像需要相机和麦克风:
  1. async function startRecording() {
  2. try {
  3. await authorize('scope.camera');
  4. await authorize('scope.record');
  5. // 两个权限都拿到了
  6. const ctx = has.createCameraContext();
  7. ctx.startRecord({ ... });
  8. } catch (err) {
  9. has.showToast({ title: '需要相机和麦克风权限' });
  10. }
  11. }
复制代码
场景二,权限拒绝后的引导。用户拒绝后再次调用 authorize 可能不再弹窗,可以提示用户去设置页手动开启:
  1. has.authorize({
  2. scope: 'scope.userLocation',
  3. fail: (err) => {
  4. has.showModal({
  5. title: '需要定位权限',
  6. content: '请在设置中开启定位权限',
  7. confirmText: '去设置',
  8. success: (res) => {
  9. if (res.confirm) {
  10. has.openSetting({
  11. success: (settingRes) => {
  12. // 检查用户是否在设置里开启了权限
  13. console.info('设置结果:', settingRes);
  14. }
  15. });
  16. }
  17. }
  18. });
  19. }
  20. });
复制代码
has.openSetting 可以打开元服务的设置页面,用户可以在那里手动开启权限。
场景三,按需申请。不要一进应用就申请所有权限,用户会烦。应该在真正需要的时候再申请:
  1. Page({
  2. // 用户点击扫一扫按钮时才申请相机权限
  3. onScanTap() {
  4. has.authorize({
  5. scope: 'scope.camera',
  6. success: () => {
  7. has.scanCode({
  8. success: (res) => {
  9. console.info('扫码结果:', res.result);
  10. }
  11. });
  12. },
  13. fail: () => {
  14. has.showToast({ title: '需要相机权限才能扫码' });
  15. }
  16. });
  17. },
  18. // 用户点击添加联系人时才申请通讯录权限
  19. onAddContact() {
  20. has.authorize({
  21. scope: 'scope.contact',
  22. success: () => {
  23. has.addPhoneContact({ ... });
  24. }
  25. });
  26. }
  27. });
复制代码

七、常见踩坑与排障
1. module.json5 没声明权限。这是最常见错误,scope 对应的系统权限必须在 requestPermissions 里声明,否则直接 fail。比如 scope.userLocation 必须声明 LOCATION 和 APPROXIMATELY_LOCATION 两个权限。
2. scope 和系统权限的对应关系不是一一对应。一个 scope 可能对应多个系统权限,漏一个都会失败。
3. 用户拒绝后不再弹窗。再次调用 has.authorize 可能直接走 fail,需要用 has.openSetting 引导用户去设置里手动开启。
4. WiFi 需要定位权限。获取 WiFi 列表需要 scope.userLocation 权限。
5. 后台定位需要额外配置。scope.userFuzzyLocation 用于前台定位;如果需要后台持续定位,除了权限,还需要在 module.json5 里配置 backgroundModes: ['location']。
6. 单次授权。HarmonyOS 支持单次授权,用户选择仅本次允许后,下次使用时需要重新申请,不要假设之前授权过就一直有效。
7. 权限分类。ASCF 的 scope 对应的都是敏感权限,所以都会弹窗。

八、小结
ASCF 授权 API 只有 has.authorize 一个方法,但它是所有需要权限 API 的前置步骤。排查时先记住三步:module.json5 声明权限、代码里 authorize、处理失败情况。用户拒绝后用 openSetting 引导,按需申请,不要一次性全申请。遇到 fail,先检查 module.json5 有没有声明对应的系统权限,再检查 scope 是否正确。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-17 14:29 , Processed in 0.027114 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部