如何管控清单文件中的权限

简介: 如何管控清单文件中的权限

前言


为什么要做权限管控呢?因为现在的隐私合规越来越严格,对于敏感权限的使用必须在 隐私协议文档中注明权限使用的目的,甚至,在公司层面中,这类权限就不允许申请。 由于我们的项目采用组件化开发,有的小伙伴可能会因为一些技术方案需要申请一些敏感权限,也就 '自作主张'直接在自己的模块声明权限,然后直接进行了需求开发与自测,到最后快上线时被安全部门通知该权限为敏感权限不允许申请,导致需求无法上车被延期。 我们需要将权限统一管理,对于敏感权限的申请必须向上报备,并且,在小伙伴引入敏感权限开发时就能立马报错,我们需要在前期就遏制住 不友好的技术方案,避免因为需求紧急而开绿色通道。


方案


方案一


动态修改合并后的清单文件,遍历 uses-permission 节点,如果遇到不在配置内的权限,则将该节点移除,清理完之后再将最终结果回写,或是在此处直接抛出异常,将不匹配的权限打印出来提示开发人员。 优点:


  • 编译打包时自动解析,并且可以很清晰的提示开发人员

缺点:

  • 由于配置权限闭源在插件内,无法查看当前有哪些权限不符合要求,只有编译失败时才会有提示


方案二


将插件中配置的权限输出一个临时清单文件,并将该清单文件通过 sourceSet.manifest 引入参与编译,利用资源合并规则将敏感权限自动删除,如何配置删除元素可以查看官方文档的 remove 规则 优点:

  • 可以通过临时文件来查看哪些权限是敏感权限,哪些权限会保留,哪些权限会被移除

缺点:

  • 当组件模块申明的敏感权限被主工程的清单文件合并删除时无法提示,只能运行时才会表现出想申请的权限在权限设置里不存在

两种方案都能实现权限管控效果,主要看大家自己的选择,本文简要讲下 方案二 的实现


实现


1、获取主模块的清单文件,并将清单文件中的权限声明移除,避免小伙伴在主模块的清单文件中声明敏感权限运行项目


// 1、获取 main 下的清单文件,如果找不到,则手动指定清单文件
val mainAndroidManifest = project.extensions.getByType(AppExtension::class.java)
    .sourceSets.find { it.name == "main" }?.manifest?.srcFile
?: File(project.projectDir, "src/main/AndroidManifest.xml")
// 2、读取主工程下清单文件的权限,并从主工程中删除,避免有小伙伴在该文件中提交敏感权限
val parentNode = XmlParser(false, false).parse(mainAndroidManifest)
val childrenNode = parentNode.children()
val permissionNodes = childrenNode.map { it as Node }.filter { it.name() == "uses-permission" }.toList()
if (permissionNodes.isNotEmpty()) {
    // 3、移除所有权限
    childrenNode.removeAll(permissionNodes)
    val xmlText = XmlUtil.serialize(parentNode)
    // 4、回写主工程的清单文件
    mainAndroidManifest.writeText(xmlText)
}
复制代码


2、生成临时清单文件,将插件中的权限回写进临时清单文件,并通过 sourceSet 来引入参与编译


// 获取插件内配置的权限,并将权限添加进 manifest 节点
getPermission().forEach {
    childrenNode.add(0, Node(null, it))
}
// 将权限写入临时清单文件
val xmlText2 = XmlUtil.serialize(parentNode)
permissionFile.writeText(xmlText2)
project.afterEvaluate {
    // 将生成的临时清单文件添加进 main sourceSet.manifest 中参与项目编译
    project.extensions.getByType(AppExtension::class.java)
        .sourceSets.find { it.name == "main" }?.manifest?.srcFile(permissionFile)
}
复制代码


源码可查看 PermissionPlugin


扩展知识(清单文件合并)

image.png


合并优先级:合并三个清单文件的流程,从优先级最低的清单文件(左)合并到优先级最高的清单文件(右)中


因此,在组件模块中声明的权限(Library)比主工程声明的权限(main)优先级低,所以可以在优先级高的主工程模块声明 remove 规则,即可将低优先级中声明的权限进行移除,例如:

image.png

合并结果,只保留了 INTERNET 权限:

image.png


所以,我们又可以发散性思维,对于 Android 12 的 exported 适配,是不是也可以利用这种规则,对于原本需要在组件中声明的 exported,我们可以利用脚本来处理,生成和组件中一样的节点,并声明 exported 为 false,并且增加一个 merge 节点来参与合并,以此给组件原来未声明的 exported 添加上,示例如下:

image.png

合并结果如下:

image.png

目录
相关文章
|
计算机视觉
如何理解focal loss/GIOU(yolo改进损失函数)
如何理解focal loss/GIOU(yolo改进损失函数)
|
Linux C语言 C++
CentOS7安装gcc-5.4.0
CentoOS7 安装gcc
4228 0
CentOS7安装gcc-5.4.0
|
Java Spring 容器
Spring的AOP失效场景详解
Spring的AOP失效场景详解
1705 0
|
9月前
|
存储 关系型数据库 分布式数据库
PolarDB开源数据库进阶课18 通过pg_bulkload适配pfs实现批量导入提速
本文介绍了如何修改 `pg_bulkload` 工具以适配 PolarDB 的 PFS(Polar File System),从而加速批量导入数据。实验环境依赖于 Docker 容器中的 loop 设备模拟共享存储。通过对 `writer_direct.c` 文件的修改,替换了一些标准文件操作接口为 PFS 对应接口,实现了对 PolarDB 15 版本的支持。测试结果显示,使用 `pg_bulkload` 导入 1000 万条数据的速度是 COPY 命令的三倍多。此外,文章还提供了详细的步骤和代码示例,帮助读者理解和实践这一过程。
359 0
|
存储 C语言 C++
如何通过指针作为函数参数来实现函数的返回多个值
在C语言中,可以通过将指针作为函数参数来实现函数返回多个值。调用函数时,传递变量的地址,函数内部通过修改指针所指向的内存来改变原变量的值,从而实现多值返回。
|
Python
python语法错误变量未定义
【7月更文挑战第9天】
684 1
|
SQL 关系型数据库 MySQL
关系型数据库mysql跨平台兼容性
【6月更文挑战第13天】
757 4
|
Windows
Windows常用快捷键与终端命令
Windows常用快捷键 1、Ctrl + Z:撤消 无论你在做什么,Ctrl + Z都非常实用,这个功能都可以撤销当前的步骤,回到上一步未更改前,所以不要担心所有的错误。 2、Ctrl + C:复制 这可能是人们在使用Windows系统时使用的最方便的快捷键之一,轻松复制您喜欢的任何内容,直到您准备将其粘贴到任何您喜欢的位置。 3、Ctrl + V:粘贴 轻松粘贴您复制的所有内容,它可以是文本、文件、图像或文件夹,将所有东西组合在一起的非常有用的功能。
720 1
|
存储 安全 算法
c++ vector数组详细介绍(一)
c++ vector数组详细介绍(一)
506 0
|
存储 机器学习/深度学习 设计模式
笔记 - 《领域驱动设计:软件复杂性应对之道》
笔记 - 《领域驱动设计:软件复杂性应对之道》