How to manage permissions in manifest files

foreword

Why do permissions control? Because privacy compliance is becoming more and more strict, the use of sensitive permissions must indicate the purpose of the use of permissions in the 隐私协议document , and even at the company level, such permissions are not allowed to apply. Since our project adopts component development, some small partners may need to apply for some sensitive permissions because of some technical solutions, so they '自作主张'directly declare permissions in their own modules, and then directly conduct requirements development and self-testing, and finally go online soon. It was notified by the security department that the permission was a sensitive permission and it was not allowed to apply, resulting in the request being unable to get on the bus and being postponed. We need to manage permissions in a unified way. Applications for sensitive permissions must be reported and reported, and when small partners introduce sensitive permissions for development, they can immediately report errors. We need technical solutions that are curbed 不友好in avoid opening green due to urgent needs. aisle.

Program

Option One

Dynamically modify the merged manifest file, traverse the uses-permission node, remove the node if it encounters a permission that is not in the configuration, and then write back the final result after cleaning, or throw an exception directly here. Print out the mismatched permissions to prompt the developer. advantage:

  • It is automatically parsed when compiling and packaging, and can clearly prompt developers

shortcoming:

  • Since the configuration permissions are closed source in the plug-in, it is impossible to check which permissions currently do not meet the requirements. Only when the compilation fails, there will be a prompt.

Option II

Output the permissions configured in the plugin to a temporary manifest file, and import the manifest file through sourceSet.manifest to participate in the compilation, and use the resource merging rules to automatically delete sensitive permissions. How to configure the delete element can be viewed in the official document. The advantages of the remove rule:

  • Temporary files can be used to see which permissions are sensitive, which permissions will be retained, and which permissions will be removed

shortcoming:

  • When the sensitive permission declared by the component module is merged and deleted by the manifest file of the main project, it cannot be prompted.

Both schemes can achieve the effect of authority control, which mainly depends on your own choice. This article briefly discusses 方案二the implementation of

accomplish

1. Obtain the manifest file of the main module and remove the permission declaration in the manifest file to avoid small partners declaring sensitive permissions in the manifest file of the main module to run the project

// 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. Generate a temporary manifest file, write the permissions in the plug-in back into the temporary manifest file, and introduce and participate in the compilation through 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)
}

The source code can view PermissionPlugin

Extended knowledge (manifest file merge)

Merge Priority: image.pngThe process of merging three manifest files, from the lowest priority manifest file (left) to the highest priority manifest file (right)

Therefore, the permission (Library) declared in the component module has lower priority than the permission (main) declared in the main project, so the remove rule can be declared in the main project module with high priority, and the permissions declared in the lower priority can be removed. remove, for example:

image.pngMerge the results, keeping only INTERNET permissions:

image.pngTherefore, we can think divergently. For the exported adaptation of Android 12, can we also use this rule? For the exported that needs to be declared in the component, we can use the script to process and generate the same node as in the component. , and declare that exported is false, and add a merge node to participate in the merge, so as to add the original undeclared exported of the component, the example is as follows: the image.pngmerge result is as follows:

image.png

Guess you like

Origin juejin.im/post/7116145079193960461