如何将network_security_config.xml添加到expo应用程序中的清单而不弹出

问题描述 投票:0回答:2

我正在构建一个带有 expo 的应用程序。
使用 Axios 处理请求。
该API具有自签名证书。
请求在 android 7 上失败(它们在 android 9 上工作)

我在网上看到我需要将

network_security_config.xml
添加到 Android 清单中。 链接。

如何在 expo(可能是 app.json)中执行此操作而不弹出?

谢谢你!

android react-native android-manifest expo
2个回答
22
投票

我面临着类似的问题(需要使用自签名证书连接到本地 API),经过大量的研究和实验,我终于找到了解决方案。您需要创建一个 config 插件 ,这需要 Expo SDK 版本 41+。请注意,您将失去使用 Expo Go 的能力,但您将保留在托管工作流程中(即无需更改本机代码),并且您可以使用 EAS 构建来构建自定义开发客户端,这基本上是Expo Go 为您的项目量身定制。

将证书添加到您设备的用户证书列表中:

(如果您在下面的网络配置中包含(原始)证书,则可能不需要此步骤,请参阅此链接。) 转到

Settings -> Security -> Advanced -> Encryption & credentials -> Install a certificate
导入证书

确保证书确实是问题所在:

try {
    const response = await axios.post(urlPath, payload);
} catch (error) {
    console.error(error.request?._response);
}

如果您收到网络错误并且

error.request._response
显示为
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

,您就会知道您的应用不信任该证书

创建插件:

您现在将创建一个配置插件,它基本上是在 Expo 的

prebuild
阶段运行的 JS 函数,用于在构建本机项目之前修改本机配置,例如 Android 清单。

在项目根目录中,创建一个包含以下两个文件的

plugins
文件夹:

  • network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
            <certificates src="user" />
        </trust-anchors>
    </base-config>
</network-security-config>
  • trust-local-certs.js
const {AndroidConfig, withAndroidManifest } = require('@expo/config-plugins');
const {Paths} = require('@expo/config-plugins/build/android');
const path = require('path');
const fs = require('fs');
const fsPromises = fs.promises;

const { getMainApplicationOrThrow} = AndroidConfig.Manifest

const withTrustLocalCerts = config => {
    return withAndroidManifest(config, async config => {
        config.modResults = await setCustomConfigAsync(config, config.modResults);
        return config;
    });
}

async function setCustomConfigAsync(
    config,
    androidManifest
) {

    const src_file_pat = path.join(__dirname, "network_security_config.xml");
    const res_file_path = path.join(await Paths.getResourceFolderAsync(config.modRequest.projectRoot),
        "xml", "network_security_config.xml");

    const res_dir = path.resolve(res_file_path, "..");

    if (!fs.existsSync(res_dir)) {
        await fsPromises.mkdir(res_dir);
    }

    try {
        await fsPromises.copyFile(src_file_pat, res_file_path);
    } catch (e) {
        throw e;
    }

    const mainApplication = getMainApplicationOrThrow(androidManifest);
    mainApplication.$["android:networkSecurityConfig"] = "@xml/network_security_config";

    return androidManifest;
}

module.exports = withTrustLocalCerts;

运行

expo prebuild
并链接插件

为了使用该插件,您必须在项目根目录中有一个名为

app.json
的文件。我不能 100% 确定我从哪里获取该文件,但我相信它是在我第一次运行时自动创建的
expo prebuild
。注:

  • 我建议将 Expo SDK 升级到最新版本(当前为 44),因为现在
    prebuild
    命令(显然与
    eject
    相同)现在是完全可逆的(例如,它不会安装大部分附加组件)以前的依赖项)。
  • Prebuild 将创建本机文件夹,但是一旦完成插件设置,您就可以安全地删除这些文件夹(如果您想保留在托管工作流程中,您确实应该删除它们!当您运行 EAS 构建时,EAS 会假设如果看到本机文件夹,则为裸工作流程,并且可能不会再次运行您的插件)。
  1. 运行
    expo prebuild
    并按照提示操作 -> 这应该创建
    app.json
    文件。
  2. 删除生成的本机
    android
    文件夹(以及
    ios
    ,如果也创建了)。
  3. app.json
    中,将以下内容添加到
    expo
    键的末尾:
    "plugins": [
      "./plugins/trust-local-certs.js"
    ]   
    
  4. 运行
    expo prebuild --no-install
    并检查
    android/app/src/main/AndroidManifest.xml
    是否包含对您的网络配置的引用,并且
    android/app/src/main/res/xml/network_security_config.xml
    是否已从您的
    plugins
    目录中正确复制。
  5. 如果一切顺利,您的插件设置正确,您应该再次删除本机文件夹(请参阅上面的注释)。

设置并运行 EAS 构建:

如果您还没有这样做,请按照以下步骤设置 EAS 构建项目 这些说明(安装 EAS CLI,运行 eas build:configure

 并在 
eas.json
 中配置开发配置文件)。然后,运行
eas build --profile development --platform android
。这将在云中创建一个自定义开发客户端(在 
prebuild
 阶段运行插件),您可以将其安装在您的设备上并充当 Expo Go 的替代品。要启动 Metro 服务器,请运行 
expo start --dev-client
。然后,您的开发客户端应该能够建立与 Metro 服务器的连接,并且如果您再次运行 axios 请求,它应该会通过:)


0
投票
有一个 Expo 配置插件

https://www.npmjs.com/package/expo-network-security-config 基于 silentsurfer 答案!

© www.soinside.com 2019 - 2024. All rights reserved.