HarmonyOS 5开发从入门到精通(十二):权限管理与安全
HarmonyOS 5开发从入门到精通(十二):权限管理与安全
权限管理是HarmonyOS应用开发中至关重要的一环,它保护用户隐私和设备安全。本章将详细介绍权限申请、权限检查、敏感数据保护等安全相关功能。
一、权限系统概述
1.1 权限类型
HarmonyOS权限分为两大类:
普通权限:系统自动授予,无需用户确认
- 网络访问
- 振动
- 蓝牙
敏感权限:需要用户明确授权
- 相机
- 位置
- 麦克风
- 存储
- 通讯录
1.2 权限声明
在module.json5中声明所需权限:
{
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
"reason": "需要拍照功能",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "always"
}
},
{
"name": "ohos.permission.LOCATION",
"reason": "需要获取位置信息",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "always"
}
}
]
}
二、权限申请
2.1 单次权限申请
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
async function requestCameraPermission() {
try {
const atManager = abilityAccessCtrl.createAtManager();
const permissions = ['ohos.permission.CAMERA'];
const result = await atManager.requestPermissionsFromUser(
getContext(),
permissions
);
if (result.authResults[0] === 0) {
console.log('相机权限已授权');
return true;
} else {
console.log('相机权限被拒绝');
return false;
}
} catch (error) {
console.error('权限申请失败:', error);
return false;
}
}
2.2 批量权限申请
async function requestMultiplePermissions() {
const atManager = abilityAccessCtrl.createAtManager();
const permissions = [
'ohos.permission.CAMERA',
'ohos.permission.MICROPHONE',
'ohos.permission.LOCATION'
];
const result = await atManager.requestPermissionsFromUser(
getContext(),
permissions
);
const granted = result.authResults.every(status => status === 0);
return granted;
}
三、权限检查
3.1 检查权限状态
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
async function checkPermission(permission: string): Promise<boolean> {
const atManager = abilityAccessCtrl.createAtManager();
const result = await atManager.checkAccessToken(
getContext(),
permission
);
return result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}
// 使用示例
const hasCamera = await checkPermission('ohos.permission.CAMERA');
const hasLocation = await checkPermission('ohos.permission.LOCATION');
3.2 权限状态监听
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
function setupPermissionListener() {
const atManager = abilityAccessCtrl.createAtManager();
atManager.on('permissionChange', (permissionName, grantStatus) => {
console.log(`权限 ${permissionName} 状态变为: ${grantStatus}`);
if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
// 权限被授予,执行相关操作
this.onPermissionGranted(permissionName);
} else {
// 权限被拒绝或撤销
this.onPermissionDenied(permissionName);
}
});
}
四、权限使用最佳实践
4.1 按需申请权限
@Component
struct CameraComponent {
@State hasCameraPermission: boolean = false;
@State showPermissionDialog: boolean = false;
async aboutToAppear() {
this.hasCameraPermission = await this.checkCameraPermission();
}
async checkCameraPermission(): Promise<boolean> {
const atManager = abilityAccessCtrl.createAtManager();
const result = await atManager.checkAccessToken(
getContext(),
'ohos.permission.CAMERA'
);
return result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}
async requestCameraPermission() {
const atManager = abilityAccessCtrl.createAtManager();
const result = await atManager.requestPermissionsFromUser(
getContext(),
['ohos.permission.CAMERA']
);
this.hasCameraPermission = result.authResults[0] === 0;
if (!this.hasCameraPermission) {
this.showPermissionDialog = true;
}
}
openSettings() {
// 引导用户去设置页面开启权限
// 实际实现需要使用系统API
console.log('打开设置页面');
}
build() {
Column() {
if (this.hasCameraPermission) {
// 显示相机功能
Text('相机功能已开启')
.fontSize(16)
} else {
Button('开启相机权限')
.onClick(() => this.requestCameraPermission())
.margin(20)
}
if (this.showPermissionDialog) {
Text('需要相机权限才能使用拍照功能')
.fontSize(14)
.margin(10)
Button('去设置')
.onClick(() => this.openSettings())
.margin(10)
}
}
}
}
五、数据加密与安全
5.1 数据加密存储
import cryptoFramework from '@ohos.security.cryptoFramework';
async function encryptData(data: string, key: string): Promise<string> {
try {
const cipher = cryptoFramework.createCipher('AES256');
const keyBlob = cryptoFramework.createKey(key);
await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyBlob);
const dataBlob = cryptoFramework.createDataBlob(data);
const encryptedBlob = await cipher.doFinal(dataBlob);
return encryptedBlob.toString();
} catch (error) {
console.error('加密失败:', error);
throw error;
}
}
async function decryptData(encryptedData: string, key: string): Promise<string> {
try {
const cipher = cryptoFramework.createCipher('AES256');
const keyBlob = cryptoFramework.createKey(key);
await cipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyBlob);
const dataBlob = cryptoFramework.createDataBlob(encryptedData);
const decryptedBlob = await cipher.doFinal(dataBlob);
return decryptedBlob.toString();
} catch (error) {
console.error('解密失败:', error);
throw error;
}
}
5.2 安全存储敏感数据
import preferences from '@ohos.data.preferences';
class SecureStorage {
private prefs: preferences.Preferences | null = null;
async init() {
this.prefs = await preferences.getPreferences(getContext(), 'secure_data');
}
async saveSecureData(key: string, value: string) {
if (!this.prefs) await this.init();
await this.prefs!.put(key, value);
await this.prefs!.flush();
}
async getSecureData(key: string): Promise<string | null> {
if (!this.prefs) await this.init();
return await this.prefs!.get(key, null);
}
async deleteSecureData(key: string) {
if (!this.prefs) await this.init();
await this.prefs!.delete(key);
await this.prefs!.flush();
}
}
六、网络安全
6.1 HTTPS请求
import http from '@ohos.net.http';
async function secureHttpRequest(url: string, data: any) {
try {
const httpRequest = http.createHttp();
const options = {
method: http.RequestMethod.POST,
header: {
'Content-Type': 'application/json'
},
readTimeout: 30000,
connectTimeout: 30000,
usingProtocol: http.HttpProtocol.HTTPS // 强制使用HTTPS
};
const response = await httpRequest.request(url, options);
if (response.responseCode === 200) {
return JSON.parse(response.result);
} else {
throw new Error(`请求失败: ${response.responseCode}`);
}
} catch (error) {
console.error('网络请求错误:', error);
throw error;
}
}
6.2 证书校验
import http from '@ohos.net.http';
async function secureRequestWithCertPinning() {
const httpRequest = http.createHttp();
const options = {
method: http.RequestMethod.GET,
caPath: '/system/etc/security/cacerts', // 系统证书路径
clientCert: {
certPath: '/data/cert/client.pem',
keyPath: '/data/cert/client.key'
}
};
const response = await httpRequest.request('https://api.example.com', options);
return response.result;
}
七、应用沙盒与数据隔离
7.1 应用沙盒目录
import fileio from '@ohos.fileio';
// 获取应用沙盒目录
const context = getContext();
const filesDir = context.filesDir; // /data/app/包名/files
const cacheDir = context.cacheDir; // /data/app/包名/cache
const tempDir = context.tempDir; // /data/app/包名/temp
const databaseDir = context.databaseDir; // /data/app/包名/database
7.2 安全文件操作
import fs from '@ohos.file.fs';
async function writeSecureFile(filename: string, content: string) {
const filePath = `${getContext().filesDir}/${filename}`;
try {
// 检查文件是否存在
let file = await fs.open(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
// 设置文件权限为私有
await fs.chmod(filePath, 0o600);
// 写入数据
await fs.write(file.fd, content);
await fs.close(file.fd);
console.log('文件写入成功');
} catch (error) {
console.error('文件写入失败:', error);
throw error;
}
}
八、实战案例:权限管理组件
@Component
struct PermissionManager {
@State cameraPermission: boolean = false;
@State locationPermission: boolean = false;
@State microphonePermission: boolean = false;
async aboutToAppear() {
await this.checkAllPermissions();
}
async checkAllPermissions() {
this.cameraPermission = await this.checkPermission('ohos.permission.CAMERA');
this.locationPermission = await this.checkPermission('ohos.permission.LOCATION');
this.microphonePermission = await this.checkPermission('ohos.permission.MICROPHONE');
}
async checkPermission(permission: string): Promise<boolean> {
const atManager = abilityAccessCtrl.createAtManager();
const result = await atManager.checkAccessToken(getContext(), permission);
return result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}
async requestPermission(permission: string): Promise<boolean> {
const atManager = abilityAccessCtrl.createAtManager();
const result = await atManager.requestPermissionsFromUser(getContext(), [permission]);
return result.authResults[0] === 0;
}
build() {
Column({ space: 15 }) {
Text('权限管理')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
this.buildPermissionItem('相机权限', this.cameraPermission, 'ohos.permission.CAMERA')
this.buildPermissionItem('位置权限', this.locationPermission, 'ohos.permission.LOCATION')
this.buildPermissionItem('麦克风权限', this.microphonePermission, 'ohos.permission.MICROPHONE')
}
.padding(20)
}
@Builder
buildPermissionItem(label: string, granted: boolean, permission: string) {
Row() {
Text(label)
.fontSize(16)
.layoutWeight(1)
if (granted) {
Text('已授权')
.fontColor(Color.Green)
.fontSize(14)
} else {
Button('申请权限')
.onClick(async () => {
const result = await this.requestPermission(permission);
if (result) {
await this.checkAllPermissions();
}
})
.height(30)
}
}
.width('100%')
.padding(10)
.backgroundColor('#F5F5F5')
.borderRadius(8)
}
}
九、安全最佳实践
9.1 权限申请时机
推荐做法:
- 在用户需要使用功能时申请权限
- 提供清晰的权限说明
- 解释为什么需要该权限
避免做法:
- 应用启动时一次性申请所有权限
- 强制用户授权否则无法使用应用
9.2 数据保护
- 敏感数据加密存储
- 网络传输使用HTTPS
- 避免在日志中输出敏感信息
- 及时清理临时文件
9.3 代码混淆
在build-profile.json5中配置:
{
"buildOption": {
"proguard": {
"enabled": true,
"rules": "proguard-rules.pro"
}
}
}
十、总结
本章详细介绍了HarmonyOS的权限管理与安全开发:
✅ 权限系统 - 普通权限和敏感权限的区别
✅ 权限申请 - 单次和批量权限申请
✅ 权限检查 - 检查权限状态和监听变化
✅ 数据加密 - 敏感数据加密存储
✅ 网络安全 - HTTPS请求和证书校验
✅ 应用沙盒 - 安全文件操作和数据隔离
✅ 最佳实践 - 权限申请时机和数据保护
核心要点:
- 按需申请权限,不要一次性申请所有权限
- 敏感数据必须加密存储
- 网络请求必须使用HTTPS
- 及时清理临时文件和缓存
- 遵循最小权限原则
通过合理使用权限管理和安全技术,可以保护用户隐私,提升应用的安全性。
浙公网安备 33010602011771号